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) 24c2c66affSColin Finck * 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> 32c2c66affSColin Finck 33c2c66affSColin Finck #define NDEBUG 34c2c66affSColin Finck #include <debug.h> 35c2c66affSColin Finck 36c2c66affSColin Finck /* DEFINES *******************************************************************/ 37c2c66affSColin Finck 38c2c66affSColin Finck #define KEY_BS 8 39c2c66affSColin Finck #define KEY_ESC 27 40c2c66affSColin Finck #define KEY_DEL 127 41c2c66affSColin Finck 42c2c66affSColin Finck #define KEY_SCAN_UP 72 43c2c66affSColin Finck #define KEY_SCAN_DOWN 80 44c2c66affSColin Finck 45c2c66affSColin Finck /* Scan codes of keyboard keys: */ 46c2c66affSColin Finck #define KEYSC_END 0x004f 47c2c66affSColin Finck #define KEYSC_PAGEUP 0x0049 48c2c66affSColin Finck #define KEYSC_PAGEDOWN 0x0051 49c2c66affSColin Finck #define KEYSC_HOME 0x0047 50c2c66affSColin Finck #define KEYSC_ARROWUP 0x0048 51c2c66affSColin Finck 52c2c66affSColin Finck #define KDB_ENTER_CONDITION_TO_STRING(cond) \ 53c2c66affSColin Finck ((cond) == KdbDoNotEnter ? "never" : \ 54c2c66affSColin Finck ((cond) == KdbEnterAlways ? "always" : \ 55c2c66affSColin Finck ((cond) == KdbEnterFromKmode ? "kmode" : "umode"))) 56c2c66affSColin Finck 57c2c66affSColin Finck #define KDB_ACCESS_TYPE_TO_STRING(type) \ 58c2c66affSColin Finck ((type) == KdbAccessRead ? "read" : \ 59c2c66affSColin Finck ((type) == KdbAccessWrite ? "write" : \ 60c2c66affSColin Finck ((type) == KdbAccessReadWrite ? "rdwr" : "exec"))) 61c2c66affSColin Finck 62c2c66affSColin Finck #define NPX_STATE_TO_STRING(state) \ 63c2c66affSColin Finck ((state) == NPX_STATE_LOADED ? "Loaded" : \ 64c2c66affSColin Finck ((state) == NPX_STATE_NOT_LOADED ? "Not loaded" : "Unknown")) 65c2c66affSColin Finck 66c2c66affSColin Finck /* PROTOTYPES ****************************************************************/ 67c2c66affSColin Finck 68c2c66affSColin Finck static BOOLEAN KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[]); 69c2c66affSColin Finck static BOOLEAN KdbpCmdDisassembleX(ULONG Argc, PCHAR Argv[]); 70c2c66affSColin Finck static BOOLEAN KdbpCmdRegs(ULONG Argc, PCHAR Argv[]); 71c2c66affSColin Finck static BOOLEAN KdbpCmdBackTrace(ULONG Argc, PCHAR Argv[]); 72c2c66affSColin Finck 73c2c66affSColin Finck static BOOLEAN KdbpCmdContinue(ULONG Argc, PCHAR Argv[]); 74c2c66affSColin Finck static BOOLEAN KdbpCmdStep(ULONG Argc, PCHAR Argv[]); 75c2c66affSColin Finck static BOOLEAN KdbpCmdBreakPointList(ULONG Argc, PCHAR Argv[]); 76c2c66affSColin Finck static BOOLEAN KdbpCmdEnableDisableClearBreakPoint(ULONG Argc, PCHAR Argv[]); 77c2c66affSColin Finck static BOOLEAN KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[]); 78c2c66affSColin Finck 79c2c66affSColin Finck static BOOLEAN KdbpCmdThread(ULONG Argc, PCHAR Argv[]); 80c2c66affSColin Finck static BOOLEAN KdbpCmdProc(ULONG Argc, PCHAR Argv[]); 81c2c66affSColin Finck 82c2c66affSColin Finck static BOOLEAN KdbpCmdMod(ULONG Argc, PCHAR Argv[]); 83c2c66affSColin Finck static BOOLEAN KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[]); 84c2c66affSColin Finck static BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[]); 853726b992SJérôme Gardou #ifdef _M_IX86 86c2c66affSColin Finck static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]); 873726b992SJérôme Gardou #endif 88c2c66affSColin Finck 89c2c66affSColin Finck static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]); 90c2c66affSColin Finck static BOOLEAN KdbpCmdReboot(ULONG Argc, PCHAR Argv[]); 91c2c66affSColin Finck static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]); 92c2c66affSColin Finck static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]); 93c2c66affSColin Finck static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]); 94c2c66affSColin Finck static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]); 95c2c66affSColin Finck 96c2c66affSColin Finck BOOLEAN ExpKdbgExtPool(ULONG Argc, PCHAR Argv[]); 9778b55550SPierre Schweitzer BOOLEAN ExpKdbgExtPoolUsed(ULONG Argc, PCHAR Argv[]); 9812e57956SPierre Schweitzer BOOLEAN ExpKdbgExtPoolFind(ULONG Argc, PCHAR Argv[]); 99cb52c821SPierre Schweitzer BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]); 100d35243d4SPierre Schweitzer BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]); 10147b48520SPierre Schweitzer BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]); 1022991f6e7SPierre Schweitzer BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]); 103d6dc1fd2SPierre Schweitzer 104c2c66affSColin Finck #ifdef __ROS_DWARF__ 105c2c66affSColin Finck static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]); 106c2c66affSColin Finck #endif 107c2c66affSColin Finck 1083726b992SJérôme Gardou /* Be more descriptive than intrinsics */ 1093726b992SJérôme Gardou #ifndef Ke386GetGlobalDescriptorTable 1103726b992SJérôme Gardou # define Ke386GetGlobalDescriptorTable __sgdt 1113726b992SJérôme Gardou #endif 1123726b992SJérôme Gardou #ifndef Ke386GetLocalDescriptorTable 1133726b992SJérôme Gardou # define Ke386GetLocalDescriptorTable __sldt 1143726b992SJérôme Gardou #endif 1153726b992SJérôme Gardou 1163726b992SJérôme Gardou /* Portability */ 1173726b992SJérôme Gardou FORCEINLINE 1183726b992SJérôme Gardou ULONG_PTR 1193726b992SJérôme Gardou strtoulptr(const char* nptr, char** endptr, int base) 1203726b992SJérôme Gardou { 1213726b992SJérôme Gardou #ifdef _M_IX86 1223726b992SJérôme Gardou return strtoul(nptr, endptr, base); 1233726b992SJérôme Gardou #else 1243726b992SJérôme Gardou return strtoull(nptr, endptr, base); 1253726b992SJérôme Gardou #endif 1263726b992SJérôme Gardou } 1273726b992SJérôme Gardou 128c2c66affSColin Finck /* GLOBALS *******************************************************************/ 129c2c66affSColin Finck 130ba37323aSHervé Poussineau typedef 131ba37323aSHervé Poussineau BOOLEAN 132ba37323aSHervé Poussineau (NTAPI *PKDBG_CLI_ROUTINE)( 133ba37323aSHervé Poussineau IN PCHAR Command, 134ba37323aSHervé Poussineau IN ULONG Argc, 135ba37323aSHervé Poussineau IN PCH Argv[]); 136ba37323aSHervé Poussineau 137c2c66affSColin Finck static PKDBG_CLI_ROUTINE KdbCliCallbacks[10]; 138c2c66affSColin Finck static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */ 139c2c66affSColin Finck static BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a module is loaded */ 140c2c66affSColin Finck 141c2c66affSColin Finck static CHAR KdbCommandHistoryBuffer[2048]; /* Command history string ringbuffer */ 142c2c66affSColin Finck static PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL }; /* Command history ringbuffer */ 143c2c66affSColin Finck static LONG KdbCommandHistoryBufferIndex = 0; 144c2c66affSColin Finck static LONG KdbCommandHistoryIndex = 0; 145c2c66affSColin Finck 146c2c66affSColin Finck static ULONG KdbNumberOfRowsPrinted = 0; 147c2c66affSColin Finck static ULONG KdbNumberOfColsPrinted = 0; 148c2c66affSColin Finck static BOOLEAN KdbOutputAborted = FALSE; 149c2c66affSColin Finck static BOOLEAN KdbRepeatLastCommand = FALSE; 150c2c66affSColin Finck static LONG KdbNumberOfRowsTerminal = -1; 151c2c66affSColin Finck static LONG KdbNumberOfColsTerminal = -1; 152c2c66affSColin Finck 153c2c66affSColin Finck PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */ 154c2c66affSColin Finck BOOLEAN KdbpBugCheckRequested = FALSE; 155c2c66affSColin Finck 156c2c66affSColin Finck /* Vars for dmesg */ 157c2c66affSColin Finck /* defined in ../kd/kdio.c, declare here: */ 158c2c66affSColin Finck extern volatile BOOLEAN KdbpIsInDmesgMode; 159c2c66affSColin Finck extern const ULONG KdpDmesgBufferSize; 160c2c66affSColin Finck extern PCHAR KdpDmesgBuffer; 161c2c66affSColin Finck extern volatile ULONG KdpDmesgCurrentPosition; 162c2c66affSColin Finck extern volatile ULONG KdpDmesgFreeBytes; 163c2c66affSColin Finck extern volatile ULONG KdbDmesgTotalWritten; 164c2c66affSColin Finck 165a890fc64SHermès Bélusca-Maïto STRING KdbPromptString = RTL_CONSTANT_STRING("kdb:> "); 166a890fc64SHermès Bélusca-Maïto 16740c57de7SHermès Bélusca-Maïto // 16840c57de7SHermès Bélusca-Maïto // Debug Filter Component Table 16940c57de7SHermès Bélusca-Maïto // 1707d3dac32SHermès Bélusca-Maïto #define KD_DEBUG_PRINT_FILTER(Name) \ 1717d3dac32SHermès Bélusca-Maïto { #Name, DPFLTR_##Name##_ID } 1727d3dac32SHermès Bélusca-Maïto 173c2c66affSColin Finck static struct 174c2c66affSColin Finck { 17540c57de7SHermès Bélusca-Maïto PCSTR Name; 176c2c66affSColin Finck ULONG Id; 177c2c66affSColin Finck } 178c2c66affSColin Finck ComponentTable[] = 179c2c66affSColin Finck { 1806c1aac69SHermès Bélusca-Maïto // 1816c1aac69SHermès Bélusca-Maïto // Default components 1826c1aac69SHermès Bélusca-Maïto // 1836c1aac69SHermès Bélusca-Maïto { "WIN2000", MAXULONG }, 1847d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DEFAULT), 1856c1aac69SHermès Bélusca-Maïto // 1866c1aac69SHermès Bélusca-Maïto // Standard components 1876c1aac69SHermès Bélusca-Maïto // 1887d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SYSTEM), 1897d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SMSS), 1907d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SETUP), 1917d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(NTFS), 1927d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FSTUB), 1937d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CRASHDUMP), 1947d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CDAUDIO), 1957d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CDROM), 1967d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CLASSPNP), 1977d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DISK), 1987d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(REDBOOK), 1997d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(STORPROP), 2007d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SCSIPORT), 2017d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SCSIMINIPORT), 2027d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CONFIG), 2037d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(I8042PRT), 2047d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SERMOUSE), 2057d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(LSERMOUS), 2067d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(KBDHID), 2077d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(MOUHID), 2087d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(KBDCLASS), 2097d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(MOUCLASS), 2107d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(TWOTRACK), 2117d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(WMILIB), 2127d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(ACPI), 2137d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(AMLI), 2147d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(HALIA64), 2157d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VIDEO), 2167d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SVCHOST), 2177d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VIDEOPRT), 2187d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(TCPIP), 2197d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DMSYNTH), 2207d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(NTOSPNP), 2217d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FASTFAT), 2227d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SAMSS), 2237d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PNPMGR), 2247d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(NETAPI), 2257d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SCSERVER), 2267d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SCCLIENT), 2277d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SERIAL), 2287d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SERENUM), 2297d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(UHCD), 2307d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(RPCPROXY), 2317d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(AUTOCHK), 2327d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DCOMSS), 2337d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(UNIMODEM), 2347d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SIS), 2357d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FLTMGR), 2367d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(WMICORE), 2377d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(BURNENG), 2387d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IMAPI), 2397d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SXS), 2407d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FUSION), 2417d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IDLETASK), 2427d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SOFTPCI), 2437d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(TAPE), 2447d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(MCHGR), 2457d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IDEP), 2467d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PCIIDE), 2477d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FLOPPY), 2487d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FDC), 2497d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(TERMSRV), 2507d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(W32TIME), 2517d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PREFETCHER), 2527d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(RSFILTER), 2537d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FCPORT), 2547d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PCI), 2557d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DMIO), 2567d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DMCONFIG), 2577d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DMADMIN), 2587d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(WSOCKTRANSPORT), 2597d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VSS), 2607d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PNPMEM), 2617d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PROCESSOR), 2627d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DMSERVER), 2637d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SR), 2647d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(INFINIBAND), 2657d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IHVDRIVER), 2667d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IHVVIDEO), 2677d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IHVAUDIO), 2687d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IHVNETWORK), 2697d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IHVSTREAMING), 2707d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IHVBUS), 2717d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(HPS), 2727d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(RTLTHREADPOOL), 2737d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(LDR), 2747d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(TCPIP6), 2757d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(ISAPNP), 2767d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SHPC), 2777d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(STORPORT), 2787d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(STORMINIPORT), 2797d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PRINTSPOOLER), 2807d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VSSDYNDISK), 2817d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VERIFIER), 2827d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VDS), 2837d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VDSBAS), 2847d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VDSDYN), // Specified in Vista+ 2857d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VDSDYNDR), 2867d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VDSLDR), // Specified in Vista+ 2877d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VDSUTIL), 2887d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DFRGIFC), 2897d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(MM), 2907d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DFSC), 2917d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(WOW64), 2926c1aac69SHermès Bélusca-Maïto // 2936c1aac69SHermès Bélusca-Maïto // Components specified in Vista+, some of which we also use in ReactOS 2946c1aac69SHermès Bélusca-Maïto // 2957d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(ALPC), 2967d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(WDI), 2977d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PERFLIB), 2987d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(KTM), 2997d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(IOSTRESS), 3007d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(HEAP), 3017d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(WHEA), 3027d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(USERGDI), 3037d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(MMCSS), 3047d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(TPM), 3057d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(THREADORDER), 3067d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(ENVIRON), 3077d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(EMS), 3087d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(WDT), 3097d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FVEVOL), 3107d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(NDIS), 3117d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(NVCTRACE), 3127d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(LUAFV), 3137d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(APPCOMPAT), 3147d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(USBSTOR), 3157d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SBP2PORT), 3167d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(COVERAGE), 3177d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CACHEMGR), 3187d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(MOUNTMGR), 3197d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CFR), 3207d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(TXF), 3217d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(KSECDD), 3227d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FLTREGRESS), 3237d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(MPIO), 3247d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(MSDSM), 3257d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(UDFS), 3267d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(PSHED), 3277d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(STORVSP), 3287d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(LSASS), 3297d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SSPICLI), 3307d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CNG), 3317d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(EXFAT), 3327d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FILETRACE), 3337d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(XSAVE), 3347d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(SE), 3357d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(DRIVEEXTENDER), 336ceb58c82SHermès Bélusca-Maïto // 337ceb58c82SHermès Bélusca-Maïto // Components specified in Windows 8 338ceb58c82SHermès Bélusca-Maïto // 3397d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(POWER), 3407d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CRASHDUMPXHCI), 3417d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(GPIO), 3427d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(REFS), 3437d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(WER), 344ceb58c82SHermès Bélusca-Maïto // 345ceb58c82SHermès Bélusca-Maïto // Components specified in Windows 10 346ceb58c82SHermès Bélusca-Maïto // 3477d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(CAPIMG), 3487d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(VPCI), 3497d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(STORAGECLASSMEMORY), 3507d3dac32SHermès Bélusca-Maïto KD_DEBUG_PRINT_FILTER(FSLIB), 351c2c66affSColin Finck }; 3527d3dac32SHermès Bélusca-Maïto #undef KD_DEBUG_PRINT_FILTER 353c2c66affSColin Finck 35440c57de7SHermès Bélusca-Maïto // 35540c57de7SHermès Bélusca-Maïto // Command Table 35640c57de7SHermès Bélusca-Maïto // 35740c57de7SHermès Bélusca-Maïto static const struct 358c2c66affSColin Finck { 35940c57de7SHermès Bélusca-Maïto PCHAR Name; 36040c57de7SHermès Bélusca-Maïto PCHAR Syntax; 36140c57de7SHermès Bélusca-Maïto PCHAR Help; 36240c57de7SHermès Bélusca-Maïto BOOLEAN (*Fn)(ULONG Argc, PCHAR Argv[]); 36340c57de7SHermès Bélusca-Maïto } KdbDebuggerCommands[] = { 36440c57de7SHermès Bélusca-Maïto /* Data */ 36540c57de7SHermès Bélusca-Maïto { NULL, NULL, "Data", NULL }, 36640c57de7SHermès Bélusca-Maïto { "?", "? expression", "Evaluate expression.", KdbpCmdEvalExpression }, 36740c57de7SHermès Bélusca-Maïto { "disasm", "disasm [address] [L count]", "Disassemble count instructions at address.", KdbpCmdDisassembleX }, 36840c57de7SHermès Bélusca-Maïto { "x", "x [address] [L count]", "Display count dwords, starting at address.", KdbpCmdDisassembleX }, 36940c57de7SHermès Bélusca-Maïto { "regs", "regs", "Display general purpose registers.", KdbpCmdRegs }, 37040c57de7SHermès Bélusca-Maïto { "sregs", "sregs", "Display status registers.", KdbpCmdRegs }, 37140c57de7SHermès Bélusca-Maïto { "dregs", "dregs", "Display debug registers.", KdbpCmdRegs }, 37240c57de7SHermès Bélusca-Maïto { "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame address.", KdbpCmdBackTrace }, 37340c57de7SHermès Bélusca-Maïto #ifdef __ROS_DWARF__ 37440c57de7SHermès Bélusca-Maïto { "dt", "dt [mod] [type] [addr]", "Print a struct. The address is optional.", KdbpCmdPrintStruct }, 37540c57de7SHermès Bélusca-Maïto #endif 376c2c66affSColin Finck 37740c57de7SHermès Bélusca-Maïto /* Flow control */ 37840c57de7SHermès Bélusca-Maïto { NULL, NULL, "Flow control", NULL }, 37940c57de7SHermès Bélusca-Maïto { "cont", "cont", "Continue execution (leave debugger).", KdbpCmdContinue }, 38040c57de7SHermès Bélusca-Maïto { "step", "step [count]", "Execute single instructions, stepping into interrupts.", KdbpCmdStep }, 38140c57de7SHermès Bélusca-Maïto { "next", "next [count]", "Execute single instructions, skipping calls and reps.", KdbpCmdStep }, 38240c57de7SHermès Bélusca-Maïto { "bl", "bl", "List breakpoints.", KdbpCmdBreakPointList }, 38340c57de7SHermès Bélusca-Maïto { "be", "be [breakpoint]", "Enable breakpoint.", KdbpCmdEnableDisableClearBreakPoint }, 38440c57de7SHermès Bélusca-Maïto { "bd", "bd [breakpoint]", "Disable breakpoint.", KdbpCmdEnableDisableClearBreakPoint }, 38540c57de7SHermès Bélusca-Maïto { "bc", "bc [breakpoint]", "Clear breakpoint.", KdbpCmdEnableDisableClearBreakPoint }, 38640c57de7SHermès Bélusca-Maïto { "bpx", "bpx [address] [IF condition]", "Set software execution breakpoint at address.", KdbpCmdBreakPoint }, 38740c57de7SHermès Bélusca-Maïto { "bpm", "bpm [r|w|rw|x] [byte|word|dword] [address] [IF condition]", "Set memory breakpoint at address.", KdbpCmdBreakPoint }, 38840c57de7SHermès Bélusca-Maïto 38940c57de7SHermès Bélusca-Maïto /* Process/Thread */ 39040c57de7SHermès Bélusca-Maïto { NULL, NULL, "Process/Thread", NULL }, 39140c57de7SHermè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 }, 39240c57de7SHermès Bélusca-Maïto { "proc", "proc [list|[attach ]pid]", "List processes, display process with given id or attach to process.", KdbpCmdProc }, 39340c57de7SHermès Bélusca-Maïto 39440c57de7SHermès Bélusca-Maïto /* System information */ 39540c57de7SHermès Bélusca-Maïto { NULL, NULL, "System info", NULL }, 39640c57de7SHermès Bélusca-Maïto { "mod", "mod [address]", "List all modules or the one containing address.", KdbpCmdMod }, 39740c57de7SHermès Bélusca-Maïto { "gdt", "gdt", "Display the global descriptor table.", KdbpCmdGdtLdtIdt }, 39840c57de7SHermès Bélusca-Maïto { "ldt", "ldt", "Display the local descriptor table.", KdbpCmdGdtLdtIdt }, 39940c57de7SHermès Bélusca-Maïto { "idt", "idt", "Display the interrupt descriptor table.", KdbpCmdGdtLdtIdt }, 40040c57de7SHermès Bélusca-Maïto { "pcr", "pcr", "Display the processor control region.", KdbpCmdPcr }, 4013726b992SJérôme Gardou #ifdef _M_IX86 40240c57de7SHermè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 }, 4033726b992SJérôme Gardou #endif 40440c57de7SHermès Bélusca-Maïto 40540c57de7SHermès Bélusca-Maïto /* Others */ 40640c57de7SHermès Bélusca-Maïto { NULL, NULL, "Others", NULL }, 40740c57de7SHermès Bélusca-Maïto { "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck }, 40840c57de7SHermès Bélusca-Maïto { "reboot", "reboot", "Reboots the system.", KdbpCmdReboot}, 40940c57de7SHermès Bélusca-Maïto { "filter", "filter [error|warning|trace|info|level]+|-[componentname|default]", "Enable/disable debug channels.", KdbpCmdFilter }, 41040c57de7SHermès Bélusca-Maïto { "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet }, 41140c57de7SHermès Bélusca-Maïto { "dmesg", "dmesg", "Display debug messages on screen, with navigation on pages.", KdbpCmdDmesg }, 41240c57de7SHermès Bélusca-Maïto { "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.", KdbpCmdDmesg }, 41340c57de7SHermès Bélusca-Maïto { "help", "help", "Display help screen.", KdbpCmdHelp }, 41440c57de7SHermès Bélusca-Maïto { "!pool", "!pool [Address [Flags]]", "Display information about pool allocations.", ExpKdbgExtPool }, 41540c57de7SHermès Bélusca-Maïto { "!poolused", "!poolused [Flags [Tag]]", "Display pool usage.", ExpKdbgExtPoolUsed }, 41640c57de7SHermès Bélusca-Maïto { "!poolfind", "!poolfind Tag [Pool]", "Search for pool tag allocations.", ExpKdbgExtPoolFind }, 41740c57de7SHermès Bélusca-Maïto { "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache }, 41840c57de7SHermès Bélusca-Maïto { "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites }, 41940c57de7SHermès Bélusca-Maïto { "!irpfind", "!irpfind [Pool [startaddress [criteria data]]]", "Lists IRPs potentially matching criteria.", ExpKdbgExtIrpFind }, 42040c57de7SHermès Bélusca-Maïto { "!handle", "!handle [Handle]", "Displays info about handles.", ExpKdbgExtHandle }, 42140c57de7SHermès Bélusca-Maïto }; 42240c57de7SHermès Bélusca-Maïto 42340c57de7SHermès Bélusca-Maïto /* FUNCTIONS *****************************************************************/ 424c2c66affSColin Finck 425c2c66affSColin Finck /*!\brief Evaluates an expression... 426c2c66affSColin Finck * 427c2c66affSColin Finck * Much like KdbpRpnEvaluateExpression, but prints the error message (if any) 428c2c66affSColin Finck * at the given offset. 429c2c66affSColin Finck * 430c2c66affSColin Finck * \param Expression Expression to evaluate. 431c2c66affSColin Finck * \param ErrOffset Offset (in characters) to print the error message at. 432c2c66affSColin Finck * \param Result Receives the result on success. 433c2c66affSColin Finck * 434c2c66affSColin Finck * \retval TRUE Success. 435c2c66affSColin Finck * \retval FALSE Failure. 436c2c66affSColin Finck */ 437c2c66affSColin Finck static BOOLEAN 438c2c66affSColin Finck KdbpEvaluateExpression( 439c2c66affSColin Finck IN PCHAR Expression, 440c2c66affSColin Finck IN LONG ErrOffset, 441c2c66affSColin Finck OUT PULONGLONG Result) 442c2c66affSColin Finck { 443c2c66affSColin Finck static CHAR ErrMsgBuffer[130] = "^ "; 444c2c66affSColin Finck LONG ExpressionErrOffset = -1; 445c2c66affSColin Finck PCHAR ErrMsg = ErrMsgBuffer; 446c2c66affSColin Finck BOOLEAN Ok; 447c2c66affSColin Finck 448c2c66affSColin Finck Ok = KdbpRpnEvaluateExpression(Expression, KdbCurrentTrapFrame, Result, 449c2c66affSColin Finck &ExpressionErrOffset, ErrMsgBuffer + 2); 450c2c66affSColin Finck if (!Ok) 451c2c66affSColin Finck { 452c2c66affSColin Finck if (ExpressionErrOffset >= 0) 453c2c66affSColin Finck ExpressionErrOffset += ErrOffset; 454c2c66affSColin Finck else 455c2c66affSColin Finck ErrMsg += 2; 456c2c66affSColin Finck 457c2c66affSColin Finck KdbpPrint("%*s%s\n", ExpressionErrOffset, "", ErrMsg); 458c2c66affSColin Finck } 459c2c66affSColin Finck 460c2c66affSColin Finck return Ok; 461c2c66affSColin Finck } 462c2c66affSColin Finck 463c2c66affSColin Finck BOOLEAN 464c2c66affSColin Finck NTAPI 465c2c66affSColin Finck KdbpGetHexNumber( 466c2c66affSColin Finck IN PCHAR pszNum, 467c2c66affSColin Finck OUT ULONG_PTR *pulValue) 468c2c66affSColin Finck { 469c2c66affSColin Finck char *endptr; 470c2c66affSColin Finck 471c2c66affSColin Finck /* Skip optional '0x' prefix */ 472c2c66affSColin Finck if ((pszNum[0] == '0') && ((pszNum[1] == 'x') || (pszNum[1] == 'X'))) 473c2c66affSColin Finck pszNum += 2; 474c2c66affSColin Finck 475c2c66affSColin Finck /* Make a number from the string (hex) */ 476c2c66affSColin Finck *pulValue = strtoul(pszNum, &endptr, 16); 477c2c66affSColin Finck 478c2c66affSColin Finck return (*endptr == '\0'); 479c2c66affSColin Finck } 480c2c66affSColin Finck 481c2c66affSColin Finck /*!\brief Evaluates an expression and displays the result. 482c2c66affSColin Finck */ 483c2c66affSColin Finck static BOOLEAN 484c2c66affSColin Finck KdbpCmdEvalExpression( 485c2c66affSColin Finck ULONG Argc, 486c2c66affSColin Finck PCHAR Argv[]) 487c2c66affSColin Finck { 488c2c66affSColin Finck ULONG i, len; 489c2c66affSColin Finck ULONGLONG Result = 0; 490c2c66affSColin Finck ULONG ul; 491c2c66affSColin Finck LONG l = 0; 492c2c66affSColin Finck BOOLEAN Ok; 493c2c66affSColin Finck 494c2c66affSColin Finck if (Argc < 2) 495c2c66affSColin Finck { 496c2c66affSColin Finck KdbpPrint("?: Argument required\n"); 497c2c66affSColin Finck return TRUE; 498c2c66affSColin Finck } 499c2c66affSColin Finck 500c2c66affSColin Finck /* Put the arguments back together */ 501c2c66affSColin Finck Argc--; 502c2c66affSColin Finck for (i = 1; i < Argc; i++) 503c2c66affSColin Finck { 504c2c66affSColin Finck len = strlen(Argv[i]); 505c2c66affSColin Finck Argv[i][len] = ' '; 506c2c66affSColin Finck } 507c2c66affSColin Finck 508c2c66affSColin Finck /* Evaluate the expression */ 509a890fc64SHermès Bélusca-Maïto Ok = KdbpEvaluateExpression(Argv[1], KdbPromptString.Length + (Argv[1]-Argv[0]), &Result); 510c2c66affSColin Finck if (Ok) 511c2c66affSColin Finck { 512c2c66affSColin Finck if (Result > 0x00000000ffffffffLL) 513c2c66affSColin Finck { 514c2c66affSColin Finck if (Result & 0x8000000000000000LL) 515c2c66affSColin Finck KdbpPrint("0x%016I64x %20I64u %20I64d\n", Result, Result, Result); 516c2c66affSColin Finck else 517c2c66affSColin Finck KdbpPrint("0x%016I64x %20I64u\n", Result, Result); 518c2c66affSColin Finck } 519c2c66affSColin Finck else 520c2c66affSColin Finck { 521c2c66affSColin Finck ul = (ULONG)Result; 522c2c66affSColin Finck 523c2c66affSColin Finck if (ul <= 0xff && ul >= 0x80) 524c2c66affSColin Finck l = (LONG)((CHAR)ul); 525c2c66affSColin Finck else if (ul <= 0xffff && ul >= 0x8000) 526c2c66affSColin Finck l = (LONG)((SHORT)ul); 527c2c66affSColin Finck else 528c2c66affSColin Finck l = (LONG)ul; 529c2c66affSColin Finck 530c2c66affSColin Finck if (l < 0) 531c2c66affSColin Finck KdbpPrint("0x%08lx %10lu %10ld\n", ul, ul, l); 532c2c66affSColin Finck else 533c2c66affSColin Finck KdbpPrint("0x%08lx %10lu\n", ul, ul); 534c2c66affSColin Finck } 535c2c66affSColin Finck } 536c2c66affSColin Finck 537c2c66affSColin Finck return TRUE; 538c2c66affSColin Finck } 539c2c66affSColin Finck 540c2c66affSColin Finck #ifdef __ROS_DWARF__ 541c2c66affSColin Finck 542c2c66affSColin Finck /*!\brief Print a struct 543c2c66affSColin Finck */ 544c2c66affSColin Finck static VOID 545c2c66affSColin Finck KdbpPrintStructInternal 546c2c66affSColin Finck (PROSSYM_INFO Info, 547c2c66affSColin Finck PCHAR Indent, 548c2c66affSColin Finck BOOLEAN DoRead, 549c2c66affSColin Finck PVOID BaseAddress, 550c2c66affSColin Finck PROSSYM_AGGREGATE Aggregate) 551c2c66affSColin Finck { 552c2c66affSColin Finck ULONG i; 553c2c66affSColin Finck ULONGLONG Result; 554c2c66affSColin Finck PROSSYM_AGGREGATE_MEMBER Member; 555c2c66affSColin Finck ULONG IndentLen = strlen(Indent); 556c2c66affSColin Finck ROSSYM_AGGREGATE MemberAggregate = {0 }; 557c2c66affSColin Finck 558c2c66affSColin Finck for (i = 0; i < Aggregate->NumElements; i++) { 559c2c66affSColin Finck Member = &Aggregate->Elements[i]; 560c2c66affSColin Finck KdbpPrint("%s%p+%x: %s", Indent, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size, Member->Name ? Member->Name : "<anoymous>"); 561c2c66affSColin Finck if (DoRead) { 562c2c66affSColin Finck if (!strcmp(Member->Type, "_UNICODE_STRING")) { 563c2c66affSColin Finck KdbpPrint("\"%wZ\"\n", ((PCHAR)BaseAddress) + Member->BaseOffset); 564c2c66affSColin Finck continue; 565c2c66affSColin Finck } else if (!strcmp(Member->Type, "PUNICODE_STRING")) { 566c2c66affSColin Finck KdbpPrint("\"%wZ\"\n", *(((PUNICODE_STRING*)((PCHAR)BaseAddress) + Member->BaseOffset))); 567c2c66affSColin Finck continue; 568c2c66affSColin Finck } 569c2c66affSColin Finck switch (Member->Size) { 570c2c66affSColin Finck case 1: 571c2c66affSColin Finck case 2: 572c2c66affSColin Finck case 4: 573c2c66affSColin Finck case 8: { 574c2c66affSColin Finck Result = 0; 575c2c66affSColin Finck if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) { 576c2c66affSColin Finck if (Member->Bits) { 577c2c66affSColin Finck Result >>= Member->FirstBit; 578c2c66affSColin Finck Result &= ((1 << Member->Bits) - 1); 579c2c66affSColin Finck } 580c2c66affSColin Finck KdbpPrint(" %lx\n", Result); 581c2c66affSColin Finck } 582c2c66affSColin Finck else goto readfail; 583c2c66affSColin Finck break; 584c2c66affSColin Finck } 585c2c66affSColin Finck default: { 586c2c66affSColin Finck if (Member->Size < 8) { 587c2c66affSColin Finck if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) { 588c2c66affSColin Finck ULONG j; 589c2c66affSColin Finck for (j = 0; j < Member->Size; j++) { 590c2c66affSColin Finck KdbpPrint(" %02x", (int)(Result & 0xff)); 591c2c66affSColin Finck Result >>= 8; 592c2c66affSColin Finck } 593c2c66affSColin Finck } else goto readfail; 594c2c66affSColin Finck } else { 595c2c66affSColin Finck KdbpPrint(" %s @ %p {\n", Member->Type, ((PCHAR)BaseAddress) + Member->BaseOffset); 596c2c66affSColin Finck Indent[IndentLen] = ' '; 597c2c66affSColin Finck if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) { 598c2c66affSColin Finck KdbpPrintStructInternal(Info, Indent, DoRead, ((PCHAR)BaseAddress) + Member->BaseOffset, &MemberAggregate); 599c2c66affSColin Finck RosSymFreeAggregate(&MemberAggregate); 600c2c66affSColin Finck } 601c2c66affSColin Finck Indent[IndentLen] = 0; 602c2c66affSColin Finck KdbpPrint("%s}\n", Indent); 603c2c66affSColin Finck } break; 604c2c66affSColin Finck } 605c2c66affSColin Finck } 606c2c66affSColin Finck } else { 607c2c66affSColin Finck readfail: 608c2c66affSColin Finck if (Member->Size <= 8) { 609c2c66affSColin Finck KdbpPrint(" ??\n"); 610c2c66affSColin Finck } else { 611c2c66affSColin Finck KdbpPrint(" %s @ %x {\n", Member->Type, Member->BaseOffset); 612c2c66affSColin Finck Indent[IndentLen] = ' '; 613c2c66affSColin Finck if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) { 614c2c66affSColin Finck KdbpPrintStructInternal(Info, Indent, DoRead, BaseAddress, &MemberAggregate); 615c2c66affSColin Finck RosSymFreeAggregate(&MemberAggregate); 616c2c66affSColin Finck } 617c2c66affSColin Finck Indent[IndentLen] = 0; 618c2c66affSColin Finck KdbpPrint("%s}\n", Indent); 619c2c66affSColin Finck } 620c2c66affSColin Finck } 621c2c66affSColin Finck } 622c2c66affSColin Finck } 623c2c66affSColin Finck 624c2c66affSColin Finck PROSSYM_INFO KdbpSymFindCachedFile(PUNICODE_STRING ModName); 625c2c66affSColin Finck 626c2c66affSColin Finck static BOOLEAN 627c2c66affSColin Finck KdbpCmdPrintStruct( 628c2c66affSColin Finck ULONG Argc, 629c2c66affSColin Finck PCHAR Argv[]) 630c2c66affSColin Finck { 631c2c66affSColin Finck ULONG i; 632c2c66affSColin Finck ULONGLONG Result = 0; 633c2c66affSColin Finck PVOID BaseAddress = 0; 634c2c66affSColin Finck ROSSYM_AGGREGATE Aggregate = {0}; 635c2c66affSColin Finck UNICODE_STRING ModName = {0}; 636c2c66affSColin Finck ANSI_STRING AnsiName = {0}; 637c2c66affSColin Finck CHAR Indent[100] = {0}; 638c2c66affSColin Finck PROSSYM_INFO Info; 639c2c66affSColin Finck 640c2c66affSColin Finck if (Argc < 3) goto end; 641c2c66affSColin Finck AnsiName.Length = AnsiName.MaximumLength = strlen(Argv[1]); 642c2c66affSColin Finck AnsiName.Buffer = Argv[1]; 643c2c66affSColin Finck RtlAnsiStringToUnicodeString(&ModName, &AnsiName, TRUE); 644c2c66affSColin Finck Info = KdbpSymFindCachedFile(&ModName); 645c2c66affSColin Finck 646c2c66affSColin Finck if (!Info || !RosSymAggregate(Info, Argv[2], &Aggregate)) { 647c2c66affSColin Finck DPRINT1("Could not get aggregate\n"); 648c2c66affSColin Finck goto end; 649c2c66affSColin Finck } 650c2c66affSColin Finck 651c2c66affSColin Finck // Get an argument for location if it was given 652c2c66affSColin Finck if (Argc > 3) { 653c2c66affSColin Finck ULONG len; 654c2c66affSColin Finck PCHAR ArgStart = Argv[3]; 655c2c66affSColin Finck DPRINT1("Trying to get expression\n"); 656c2c66affSColin Finck for (i = 3; i < Argc - 1; i++) 657c2c66affSColin Finck { 658c2c66affSColin Finck len = strlen(Argv[i]); 659c2c66affSColin Finck Argv[i][len] = ' '; 660c2c66affSColin Finck } 661c2c66affSColin Finck 662c2c66affSColin Finck /* Evaluate the expression */ 663c2c66affSColin Finck DPRINT1("Arg: %s\n", ArgStart); 664c2c66affSColin Finck if (KdbpEvaluateExpression(ArgStart, strlen(ArgStart), &Result)) { 665c2c66affSColin Finck BaseAddress = (PVOID)(ULONG_PTR)Result; 666c2c66affSColin Finck DPRINT1("BaseAddress: %p\n", BaseAddress); 667c2c66affSColin Finck } 668c2c66affSColin Finck } 669c2c66affSColin Finck DPRINT1("BaseAddress %p\n", BaseAddress); 670c2c66affSColin Finck KdbpPrintStructInternal(Info, Indent, !!BaseAddress, BaseAddress, &Aggregate); 671c2c66affSColin Finck end: 672c2c66affSColin Finck RosSymFreeAggregate(&Aggregate); 673c2c66affSColin Finck RtlFreeUnicodeString(&ModName); 674c2c66affSColin Finck return TRUE; 675c2c66affSColin Finck } 676c2c66affSColin Finck #endif 677c2c66affSColin Finck 67840c57de7SHermès Bélusca-Maïto /*!\brief Retrieves the component ID corresponding to a given component name. 67940c57de7SHermès Bélusca-Maïto * 68040c57de7SHermès Bélusca-Maïto * \param ComponentName The name of the component. 68140c57de7SHermès Bélusca-Maïto * \param ComponentId Receives the component id on success. 68240c57de7SHermès Bélusca-Maïto * 68340c57de7SHermès Bélusca-Maïto * \retval TRUE Success. 68440c57de7SHermès Bélusca-Maïto * \retval FALSE Failure. 68540c57de7SHermès Bélusca-Maïto */ 68640c57de7SHermès Bélusca-Maïto static BOOLEAN 68740c57de7SHermès Bélusca-Maïto KdbpGetComponentId( 68840c57de7SHermès Bélusca-Maïto IN PCSTR ComponentName, 68940c57de7SHermès Bélusca-Maïto OUT PULONG ComponentId) 69040c57de7SHermès Bélusca-Maïto { 69140c57de7SHermès Bélusca-Maïto ULONG i; 69240c57de7SHermès Bélusca-Maïto 693b2eaf905SHermès Bélusca-Maïto for (i = 0; i < RTL_NUMBER_OF(ComponentTable); i++) 69440c57de7SHermès Bélusca-Maïto { 69540c57de7SHermès Bélusca-Maïto if (_stricmp(ComponentName, ComponentTable[i].Name) == 0) 69640c57de7SHermès Bélusca-Maïto { 69740c57de7SHermès Bélusca-Maïto *ComponentId = ComponentTable[i].Id; 69840c57de7SHermès Bélusca-Maïto return TRUE; 69940c57de7SHermès Bélusca-Maïto } 70040c57de7SHermès Bélusca-Maïto } 70140c57de7SHermès Bélusca-Maïto 70240c57de7SHermès Bélusca-Maïto return FALSE; 70340c57de7SHermès Bélusca-Maïto } 70440c57de7SHermès Bélusca-Maïto 70540c57de7SHermès Bélusca-Maïto /*!\brief Displays the list of active debug channels, or enable/disable debug channels. 706c2c66affSColin Finck */ 707c2c66affSColin Finck static BOOLEAN 708c2c66affSColin Finck KdbpCmdFilter( 709c2c66affSColin Finck ULONG Argc, 710c2c66affSColin Finck PCHAR Argv[]) 711c2c66affSColin Finck { 712c2c66affSColin Finck ULONG i, j, ComponentId, Level; 713c2c66affSColin Finck ULONG set = DPFLTR_MASK, clear = DPFLTR_MASK; 714c2c66affSColin Finck PCHAR pend; 71540c57de7SHermès Bélusca-Maïto PCSTR opt, p; 716c2c66affSColin Finck 717c2c66affSColin Finck static struct 718c2c66affSColin Finck { 71940c57de7SHermès Bélusca-Maïto PCSTR Name; 720c2c66affSColin Finck ULONG Level; 721c2c66affSColin Finck } 722c2c66affSColin Finck debug_classes[] = 723c2c66affSColin Finck { 724c2c66affSColin Finck { "error", 1 << DPFLTR_ERROR_LEVEL }, 725c2c66affSColin Finck { "warning", 1 << DPFLTR_WARNING_LEVEL }, 726c2c66affSColin Finck { "trace", 1 << DPFLTR_TRACE_LEVEL }, 727c2c66affSColin Finck { "info", 1 << DPFLTR_INFO_LEVEL }, 728c2c66affSColin Finck }; 729c2c66affSColin Finck 73040c57de7SHermès Bélusca-Maïto if (Argc <= 1) 73140c57de7SHermès Bélusca-Maïto { 73240c57de7SHermès Bélusca-Maïto /* Display the list of available debug filter components */ 73340c57de7SHermès Bélusca-Maïto KdbpPrint("REMARKS:\n" 73440c57de7SHermès Bélusca-Maïto "- The 'WIN2000' system-wide debug filter component is used for DbgPrint()\n" 73540c57de7SHermès Bélusca-Maïto " messages without Component ID and Level.\n" 73640c57de7SHermès Bélusca-Maïto "- The 'DEFAULT' debug filter component is used for DbgPrint() messages with\n" 73740c57de7SHermès Bélusca-Maïto " an unknown Component ID.\n\n"); 73840c57de7SHermès Bélusca-Maïto KdbpPrint("The list of debug filter components currently available on your system is:\n\n"); 73940c57de7SHermès Bélusca-Maïto KdbpPrint(" Component Name Component ID\n" 74046416a62SHermès Bélusca-Maïto " ================== ================\n"); 741b2eaf905SHermès Bélusca-Maïto for (i = 0; i < RTL_NUMBER_OF(ComponentTable); i++) 74240c57de7SHermès Bélusca-Maïto { 74346416a62SHermès Bélusca-Maïto KdbpPrint("%20s 0x%08lx\n", ComponentTable[i].Name, ComponentTable[i].Id); 74440c57de7SHermès Bélusca-Maïto } 74540c57de7SHermès Bélusca-Maïto return TRUE; 74640c57de7SHermès Bélusca-Maïto } 74740c57de7SHermès Bélusca-Maïto 748c2c66affSColin Finck for (i = 1; i < Argc; i++) 749c2c66affSColin Finck { 750c2c66affSColin Finck opt = Argv[i]; 751c2c66affSColin Finck p = opt + strcspn(opt, "+-"); 75240c57de7SHermès Bélusca-Maïto if (!p[0]) p = opt; /* Assume it's a debug channel name */ 753c2c66affSColin Finck 754c2c66affSColin Finck if (p > opt) 755c2c66affSColin Finck { 756b2eaf905SHermès Bélusca-Maïto for (j = 0; j < RTL_NUMBER_OF(debug_classes); j++) 757c2c66affSColin Finck { 758c2c66affSColin Finck SIZE_T len = strlen(debug_classes[j].Name); 759c2c66affSColin Finck if (len != (p - opt)) 760c2c66affSColin Finck continue; 76140c57de7SHermès Bélusca-Maïto if (_strnicmp(opt, debug_classes[j].Name, len) == 0) /* Found it */ 762c2c66affSColin Finck { 763c2c66affSColin Finck if (*p == '+') 764c2c66affSColin Finck set |= debug_classes[j].Level; 765c2c66affSColin Finck else 766c2c66affSColin Finck clear |= debug_classes[j].Level; 767c2c66affSColin Finck break; 768c2c66affSColin Finck } 769c2c66affSColin Finck } 770b2eaf905SHermès Bélusca-Maïto if (j == RTL_NUMBER_OF(debug_classes)) 771c2c66affSColin Finck { 772c2c66affSColin Finck Level = strtoul(opt, &pend, 0); 773c2c66affSColin Finck if (pend != p) 774c2c66affSColin Finck { 775c2c66affSColin Finck KdbpPrint("filter: bad class name '%.*s'\n", p - opt, opt); 776c2c66affSColin Finck continue; 777c2c66affSColin Finck } 778c2c66affSColin Finck if (*p == '+') 779c2c66affSColin Finck set |= Level; 780c2c66affSColin Finck else 781c2c66affSColin Finck clear |= Level; 782c2c66affSColin Finck } 783c2c66affSColin Finck } 784c2c66affSColin Finck else 785c2c66affSColin Finck { 786c2c66affSColin Finck if (*p == '-') 787c2c66affSColin Finck clear = MAXULONG; 788c2c66affSColin Finck else 789c2c66affSColin Finck set = MAXULONG; 790c2c66affSColin Finck } 791c2c66affSColin Finck if (*p == '+' || *p == '-') 792c2c66affSColin Finck p++; 793c2c66affSColin Finck 794c2c66affSColin Finck if (!KdbpGetComponentId(p, &ComponentId)) 795c2c66affSColin Finck { 796c2c66affSColin Finck KdbpPrint("filter: '%s' is not a valid component name!\n", p); 797c2c66affSColin Finck return TRUE; 798c2c66affSColin Finck } 799c2c66affSColin Finck 800c2c66affSColin Finck /* Get current mask value */ 801c2c66affSColin Finck NtSetDebugFilterState(ComponentId, set, TRUE); 802c2c66affSColin Finck NtSetDebugFilterState(ComponentId, clear, FALSE); 803c2c66affSColin Finck } 804c2c66affSColin Finck 805c2c66affSColin Finck return TRUE; 806c2c66affSColin Finck } 807c2c66affSColin Finck 808c2c66affSColin Finck /*!\brief Disassembles 10 instructions at eip or given address or 809c2c66affSColin Finck * displays 16 dwords from memory at given address. 810c2c66affSColin Finck */ 811c2c66affSColin Finck static BOOLEAN 812c2c66affSColin Finck KdbpCmdDisassembleX( 813c2c66affSColin Finck ULONG Argc, 814c2c66affSColin Finck PCHAR Argv[]) 815c2c66affSColin Finck { 816c2c66affSColin Finck ULONG Count; 817c2c66affSColin Finck ULONG ul; 818c2c66affSColin Finck INT i; 819c2c66affSColin Finck ULONGLONG Result = 0; 8203726b992SJérôme Gardou ULONG_PTR Address = KeGetContextPc(KdbCurrentTrapFrame); 821c2c66affSColin Finck LONG InstLen; 822c2c66affSColin Finck 823c2c66affSColin Finck if (Argv[0][0] == 'x') /* display memory */ 824c2c66affSColin Finck Count = 16; 825c2c66affSColin Finck else /* disassemble */ 826c2c66affSColin Finck Count = 10; 827c2c66affSColin Finck 828c2c66affSColin Finck if (Argc >= 2) 829c2c66affSColin Finck { 830c2c66affSColin Finck /* Check for [L count] part */ 831c2c66affSColin Finck ul = 0; 832c2c66affSColin Finck if (strcmp(Argv[Argc-2], "L") == 0) 833c2c66affSColin Finck { 834c2c66affSColin Finck ul = strtoul(Argv[Argc-1], NULL, 0); 835c2c66affSColin Finck if (ul > 0) 836c2c66affSColin Finck { 837c2c66affSColin Finck Count = ul; 838c2c66affSColin Finck Argc -= 2; 839c2c66affSColin Finck } 840c2c66affSColin Finck } 841c2c66affSColin Finck else if (Argv[Argc-1][0] == 'L') 842c2c66affSColin Finck { 843c2c66affSColin Finck ul = strtoul(Argv[Argc-1] + 1, NULL, 0); 844c2c66affSColin Finck if (ul > 0) 845c2c66affSColin Finck { 846c2c66affSColin Finck Count = ul; 847c2c66affSColin Finck Argc--; 848c2c66affSColin Finck } 849c2c66affSColin Finck } 850c2c66affSColin Finck 851c2c66affSColin Finck /* Put the remaining arguments back together */ 852c2c66affSColin Finck Argc--; 853c2c66affSColin Finck for (ul = 1; ul < Argc; ul++) 854c2c66affSColin Finck { 855c2c66affSColin Finck Argv[ul][strlen(Argv[ul])] = ' '; 856c2c66affSColin Finck } 857c2c66affSColin Finck Argc++; 858c2c66affSColin Finck } 859c2c66affSColin Finck 860c2c66affSColin Finck /* Evaluate the expression */ 861c2c66affSColin Finck if (Argc > 1) 862c2c66affSColin Finck { 863a890fc64SHermès Bélusca-Maïto if (!KdbpEvaluateExpression(Argv[1], KdbPromptString.Length + (Argv[1]-Argv[0]), &Result)) 864c2c66affSColin Finck return TRUE; 865c2c66affSColin Finck 866c2c66affSColin Finck if (Result > (ULONGLONG)(~((ULONG_PTR)0))) 867c2c66affSColin Finck KdbpPrint("Warning: Address %I64x is beeing truncated\n",Result); 868c2c66affSColin Finck 869c2c66affSColin Finck Address = (ULONG_PTR)Result; 870c2c66affSColin Finck } 871c2c66affSColin Finck else if (Argv[0][0] == 'x') 872c2c66affSColin Finck { 873c2c66affSColin Finck KdbpPrint("x: Address argument required.\n"); 874c2c66affSColin Finck return TRUE; 875c2c66affSColin Finck } 876c2c66affSColin Finck 877c2c66affSColin Finck if (Argv[0][0] == 'x') 878c2c66affSColin Finck { 879c2c66affSColin Finck /* Display dwords */ 880c2c66affSColin Finck ul = 0; 881c2c66affSColin Finck 882c2c66affSColin Finck while (Count > 0) 883c2c66affSColin Finck { 884c2c66affSColin Finck if (!KdbSymPrintAddress((PVOID)Address, NULL)) 88589b44cfaSHermès Bélusca-Maïto KdbpPrint("<%08x>:", Address); 886c2c66affSColin Finck else 887c2c66affSColin Finck KdbpPrint(":"); 888c2c66affSColin Finck 889c2c66affSColin Finck i = min(4, Count); 890c2c66affSColin Finck Count -= i; 891c2c66affSColin Finck 892c2c66affSColin Finck while (--i >= 0) 893c2c66affSColin Finck { 894c2c66affSColin Finck if (!NT_SUCCESS(KdbpSafeReadMemory(&ul, (PVOID)Address, sizeof(ul)))) 895c2c66affSColin Finck KdbpPrint(" ????????"); 896c2c66affSColin Finck else 897c2c66affSColin Finck KdbpPrint(" %08x", ul); 898c2c66affSColin Finck 899c2c66affSColin Finck Address += sizeof(ul); 900c2c66affSColin Finck } 901c2c66affSColin Finck 902c2c66affSColin Finck KdbpPrint("\n"); 903c2c66affSColin Finck } 904c2c66affSColin Finck } 905c2c66affSColin Finck else 906c2c66affSColin Finck { 907c2c66affSColin Finck /* Disassemble */ 908c2c66affSColin Finck while (Count-- > 0) 909c2c66affSColin Finck { 910c2c66affSColin Finck if (!KdbSymPrintAddress((PVOID)Address, NULL)) 911c2c66affSColin Finck KdbpPrint("<%08x>: ", Address); 912c2c66affSColin Finck else 913c2c66affSColin Finck KdbpPrint(": "); 914c2c66affSColin Finck 915c2c66affSColin Finck InstLen = KdbpDisassemble(Address, KdbUseIntelSyntax); 916c2c66affSColin Finck if (InstLen < 0) 917c2c66affSColin Finck { 918c2c66affSColin Finck KdbpPrint("<INVALID>\n"); 919c2c66affSColin Finck return TRUE; 920c2c66affSColin Finck } 921c2c66affSColin Finck 922c2c66affSColin Finck KdbpPrint("\n"); 923c2c66affSColin Finck Address += InstLen; 924c2c66affSColin Finck } 925c2c66affSColin Finck } 926c2c66affSColin Finck 927c2c66affSColin Finck return TRUE; 928c2c66affSColin Finck } 929c2c66affSColin Finck 930c2c66affSColin Finck /*!\brief Displays CPU registers. 931c2c66affSColin Finck */ 932c2c66affSColin Finck static BOOLEAN 933c2c66affSColin Finck KdbpCmdRegs( 934c2c66affSColin Finck ULONG Argc, 935c2c66affSColin Finck PCHAR Argv[]) 936c2c66affSColin Finck { 937baa47fa5SHervé Poussineau PCONTEXT Context = KdbCurrentTrapFrame; 938c2c66affSColin Finck INT i; 939c2c66affSColin Finck static const PCHAR EflagsBits[32] = { " CF", NULL, " PF", " BIT3", " AF", " BIT5", 940c2c66affSColin Finck " ZF", " SF", " TF", " IF", " DF", " OF", 941c2c66affSColin Finck NULL, NULL, " NT", " BIT15", " RF", " VF", 942c2c66affSColin Finck " AC", " VIF", " VIP", " ID", " BIT22", 943c2c66affSColin Finck " BIT23", " BIT24", " BIT25", " BIT26", 944c2c66affSColin Finck " BIT27", " BIT28", " BIT29", " BIT30", 945c2c66affSColin Finck " BIT31" }; 946c2c66affSColin Finck 947c2c66affSColin Finck if (Argv[0][0] == 'r') /* regs */ 948c2c66affSColin Finck { 9493726b992SJérôme Gardou #ifdef _M_IX86 950c2c66affSColin Finck KdbpPrint("CS:EIP 0x%04x:0x%08x\n" 951c2c66affSColin Finck "SS:ESP 0x%04x:0x%08x\n" 952c2c66affSColin Finck " EAX 0x%08x EBX 0x%08x\n" 953c2c66affSColin Finck " ECX 0x%08x EDX 0x%08x\n" 954c2c66affSColin Finck " ESI 0x%08x EDI 0x%08x\n" 955c2c66affSColin Finck " EBP 0x%08x\n", 956baa47fa5SHervé Poussineau Context->SegCs & 0xFFFF, Context->Eip, 957baa47fa5SHervé Poussineau Context->SegSs, Context->Esp, 958baa47fa5SHervé Poussineau Context->Eax, Context->Ebx, 959baa47fa5SHervé Poussineau Context->Ecx, Context->Edx, 960baa47fa5SHervé Poussineau Context->Esi, Context->Edi, 961baa47fa5SHervé Poussineau Context->Ebp); 9623726b992SJérôme Gardou #else 9633726b992SJérôme Gardou KdbpPrint("CS:RIP 0x%04x:0x%p\n" 9643726b992SJérôme Gardou "SS:RSP 0x%04x:0x%p\n" 9653726b992SJérôme Gardou " RAX 0x%p RBX 0x%p\n" 9663726b992SJérôme Gardou " RCX 0x%p RDX 0x%p\n" 9673726b992SJérôme Gardou " RSI 0x%p RDI 0x%p\n" 9683726b992SJérôme Gardou " RBP 0x%p\n", 9693726b992SJérôme Gardou Context->SegCs & 0xFFFF, Context->Rip, 9703726b992SJérôme Gardou Context->SegSs, Context->Rsp, 9713726b992SJérôme Gardou Context->Rax, Context->Rbx, 9723726b992SJérôme Gardou Context->Rcx, Context->Rdx, 9733726b992SJérôme Gardou Context->Rsi, Context->Rdi, 9743726b992SJérôme Gardou Context->Rbp); 9753726b992SJérôme Gardou #endif 976dc0c721fSHermès Bélusca-Maïto /* Display the EFlags */ 977baa47fa5SHervé Poussineau KdbpPrint("EFLAGS 0x%08x ", Context->EFlags); 978c2c66affSColin Finck for (i = 0; i < 32; i++) 979c2c66affSColin Finck { 980c2c66affSColin Finck if (i == 1) 981c2c66affSColin Finck { 982baa47fa5SHervé Poussineau if ((Context->EFlags & (1 << 1)) == 0) 983c2c66affSColin Finck KdbpPrint(" !BIT1"); 984c2c66affSColin Finck } 985c2c66affSColin Finck else if (i == 12) 986c2c66affSColin Finck { 987baa47fa5SHervé Poussineau KdbpPrint(" IOPL%d", (Context->EFlags >> 12) & 3); 988c2c66affSColin Finck } 989c2c66affSColin Finck else if (i == 13) 990c2c66affSColin Finck { 991c2c66affSColin Finck } 992baa47fa5SHervé Poussineau else if ((Context->EFlags & (1 << i)) != 0) 993c2c66affSColin Finck { 994c2c66affSColin Finck KdbpPrint(EflagsBits[i]); 995c2c66affSColin Finck } 996c2c66affSColin Finck } 997c2c66affSColin Finck KdbpPrint("\n"); 998c2c66affSColin Finck } 999c2c66affSColin Finck else if (Argv[0][0] == 's') /* sregs */ 1000c2c66affSColin Finck { 1001c2c66affSColin Finck KdbpPrint("CS 0x%04x Index 0x%04x %cDT RPL%d\n", 1002baa47fa5SHervé Poussineau Context->SegCs & 0xffff, (Context->SegCs & 0xffff) >> 3, 1003baa47fa5SHervé Poussineau (Context->SegCs & (1 << 2)) ? 'L' : 'G', Context->SegCs & 3); 1004c2c66affSColin Finck KdbpPrint("DS 0x%04x Index 0x%04x %cDT RPL%d\n", 1005baa47fa5SHervé Poussineau Context->SegDs, Context->SegDs >> 3, (Context->SegDs & (1 << 2)) ? 'L' : 'G', Context->SegDs & 3); 1006c2c66affSColin Finck KdbpPrint("ES 0x%04x Index 0x%04x %cDT RPL%d\n", 1007baa47fa5SHervé Poussineau Context->SegEs, Context->SegEs >> 3, (Context->SegEs & (1 << 2)) ? 'L' : 'G', Context->SegEs & 3); 1008c2c66affSColin Finck KdbpPrint("FS 0x%04x Index 0x%04x %cDT RPL%d\n", 1009baa47fa5SHervé Poussineau Context->SegFs, Context->SegFs >> 3, (Context->SegFs & (1 << 2)) ? 'L' : 'G', Context->SegFs & 3); 1010c2c66affSColin Finck KdbpPrint("GS 0x%04x Index 0x%04x %cDT RPL%d\n", 1011baa47fa5SHervé Poussineau Context->SegGs, Context->SegGs >> 3, (Context->SegGs & (1 << 2)) ? 'L' : 'G', Context->SegGs & 3); 1012c2c66affSColin Finck KdbpPrint("SS 0x%04x Index 0x%04x %cDT RPL%d\n", 1013baa47fa5SHervé Poussineau Context->SegSs, Context->SegSs >> 3, (Context->SegSs & (1 << 2)) ? 'L' : 'G', Context->SegSs & 3); 1014c2c66affSColin Finck } 1015c2c66affSColin Finck else /* dregs */ 1016c2c66affSColin Finck { 1017c2c66affSColin Finck ASSERT(Argv[0][0] == 'd'); 1018c2c66affSColin Finck KdbpPrint("DR0 0x%08x\n" 1019c2c66affSColin Finck "DR1 0x%08x\n" 1020c2c66affSColin Finck "DR2 0x%08x\n" 1021c2c66affSColin Finck "DR3 0x%08x\n" 1022c2c66affSColin Finck "DR6 0x%08x\n" 1023c2c66affSColin Finck "DR7 0x%08x\n", 1024baa47fa5SHervé Poussineau Context->Dr0, Context->Dr1, Context->Dr2, Context->Dr3, 1025baa47fa5SHervé Poussineau Context->Dr6, Context->Dr7); 1026c2c66affSColin Finck } 1027c2c66affSColin Finck 1028c2c66affSColin Finck return TRUE; 1029c2c66affSColin Finck } 1030c2c66affSColin Finck 10313726b992SJérôme Gardou #ifdef _M_IX86 10328826ee8fSHermès Bélusca-Maïto static PKTSS 10338826ee8fSHermès Bélusca-Maïto KdbpRetrieveTss( 10348826ee8fSHermès Bélusca-Maïto IN USHORT TssSelector, 10358826ee8fSHermès Bélusca-Maïto OUT PULONG pType OPTIONAL, 10368826ee8fSHermès Bélusca-Maïto IN PKDESCRIPTOR pGdtr OPTIONAL) 10378826ee8fSHermès Bélusca-Maïto { 10388826ee8fSHermès Bélusca-Maïto KDESCRIPTOR Gdtr; 10398826ee8fSHermès Bélusca-Maïto KGDTENTRY Desc; 10408826ee8fSHermès Bélusca-Maïto PKTSS Tss; 10418826ee8fSHermès Bélusca-Maïto 10428826ee8fSHermès Bélusca-Maïto /* Retrieve the Global Descriptor Table (user-provided or system) */ 10438826ee8fSHermès Bélusca-Maïto if (pGdtr) 10448826ee8fSHermès Bélusca-Maïto Gdtr = *pGdtr; 10458826ee8fSHermès Bélusca-Maïto else 10468826ee8fSHermès Bélusca-Maïto Ke386GetGlobalDescriptorTable(&Gdtr.Limit); 10478826ee8fSHermès Bélusca-Maïto 10488826ee8fSHermès Bélusca-Maïto /* Check limits */ 10498826ee8fSHermès Bélusca-Maïto if ((TssSelector & (sizeof(KGDTENTRY) - 1)) || 10508826ee8fSHermès Bélusca-Maïto (TssSelector < sizeof(KGDTENTRY)) || 10518826ee8fSHermès Bélusca-Maïto (TssSelector + sizeof(KGDTENTRY) - 1 > Gdtr.Limit)) 10528826ee8fSHermès Bélusca-Maïto { 10538826ee8fSHermès Bélusca-Maïto return NULL; 10548826ee8fSHermès Bélusca-Maïto } 10558826ee8fSHermès Bélusca-Maïto 10568826ee8fSHermès Bélusca-Maïto /* Retrieve the descriptor */ 10578826ee8fSHermès Bélusca-Maïto if (!NT_SUCCESS(KdbpSafeReadMemory(&Desc, 10588826ee8fSHermès Bélusca-Maïto (PVOID)(Gdtr.Base + TssSelector), 10598826ee8fSHermès Bélusca-Maïto sizeof(KGDTENTRY)))) 10608826ee8fSHermès Bélusca-Maïto { 10618826ee8fSHermès Bélusca-Maïto return NULL; 10628826ee8fSHermès Bélusca-Maïto } 10638826ee8fSHermès Bélusca-Maïto 10648826ee8fSHermès Bélusca-Maïto /* Check for TSS32(Avl) or TSS32(Busy) */ 10658826ee8fSHermès Bélusca-Maïto if (Desc.HighWord.Bits.Type != 9 && Desc.HighWord.Bits.Type != 11) 10668826ee8fSHermès Bélusca-Maïto { 10678826ee8fSHermès Bélusca-Maïto return NULL; 10688826ee8fSHermès Bélusca-Maïto } 10698826ee8fSHermès Bélusca-Maïto if (pType) *pType = Desc.HighWord.Bits.Type; 10708826ee8fSHermès Bélusca-Maïto 10718826ee8fSHermès Bélusca-Maïto Tss = (PKTSS)(ULONG_PTR)(Desc.BaseLow | 10728826ee8fSHermès Bélusca-Maïto Desc.HighWord.Bytes.BaseMid << 16 | 10738826ee8fSHermès Bélusca-Maïto Desc.HighWord.Bytes.BaseHi << 24); 10748826ee8fSHermès Bélusca-Maïto 10758826ee8fSHermès Bélusca-Maïto return Tss; 10768826ee8fSHermès Bélusca-Maïto } 10778826ee8fSHermès Bélusca-Maïto 1078d21ff0edSHermès Bélusca-Maïto FORCEINLINE BOOLEAN 1079d21ff0edSHermès Bélusca-Maïto KdbpIsNestedTss( 1080d21ff0edSHermès Bélusca-Maïto IN USHORT TssSelector, 1081d21ff0edSHermès Bélusca-Maïto IN PKTSS Tss) 1082c2c66affSColin Finck { 1083d21ff0edSHermès Bélusca-Maïto USHORT Backlink; 1084c2c66affSColin Finck 1085d21ff0edSHermès Bélusca-Maïto if (!Tss) 1086c2c66affSColin Finck return FALSE; 1087c2c66affSColin Finck 1088d21ff0edSHermès Bélusca-Maïto /* Retrieve the TSS Backlink */ 1089d21ff0edSHermès Bélusca-Maïto if (!NT_SUCCESS(KdbpSafeReadMemory(&Backlink, 1090c2c66affSColin Finck (PVOID)&Tss->Backlink, 1091c2c66affSColin Finck sizeof(USHORT)))) 1092d21ff0edSHermès Bélusca-Maïto { 1093c2c66affSColin Finck return FALSE; 1094d21ff0edSHermès Bélusca-Maïto } 1095c2c66affSColin Finck 1096d21ff0edSHermès Bélusca-Maïto return (Backlink != 0 && Backlink != TssSelector); 1097d21ff0edSHermès Bélusca-Maïto } 1098d21ff0edSHermès Bélusca-Maïto 1099d21ff0edSHermès Bélusca-Maïto static BOOLEAN 1100baa47fa5SHervé Poussineau KdbpContextFromPrevTss( 1101baa47fa5SHervé Poussineau IN OUT PCONTEXT Context, 1102d21ff0edSHermès Bélusca-Maïto OUT PUSHORT TssSelector, 1103d21ff0edSHermès Bélusca-Maïto IN OUT PKTSS* pTss, 1104d21ff0edSHermès Bélusca-Maïto IN PKDESCRIPTOR pGdtr) 1105d21ff0edSHermès Bélusca-Maïto { 1106d21ff0edSHermès Bélusca-Maïto ULONG_PTR Eip, Ebp; 1107d21ff0edSHermès Bélusca-Maïto USHORT Backlink; 1108d21ff0edSHermès Bélusca-Maïto PKTSS Tss = *pTss; 1109d21ff0edSHermès Bélusca-Maïto 1110d21ff0edSHermès Bélusca-Maïto /* Retrieve the TSS Backlink */ 1111d21ff0edSHermès Bélusca-Maïto if (!NT_SUCCESS(KdbpSafeReadMemory(&Backlink, 1112d21ff0edSHermès Bélusca-Maïto (PVOID)&Tss->Backlink, 1113d21ff0edSHermès Bélusca-Maïto sizeof(USHORT)))) 1114d21ff0edSHermès Bélusca-Maïto { 1115c2c66affSColin Finck return FALSE; 1116d21ff0edSHermès Bélusca-Maïto } 1117c2c66affSColin Finck 1118d21ff0edSHermès Bélusca-Maïto /* Retrieve the parent TSS */ 1119d21ff0edSHermès Bélusca-Maïto Tss = KdbpRetrieveTss(Backlink, NULL, pGdtr); 1120d21ff0edSHermès Bélusca-Maïto if (!Tss) 1121c2c66affSColin Finck return FALSE; 1122c2c66affSColin Finck 1123c2c66affSColin Finck if (!NT_SUCCESS(KdbpSafeReadMemory(&Eip, 1124c2c66affSColin Finck (PVOID)&Tss->Eip, 1125c2c66affSColin Finck sizeof(ULONG_PTR)))) 1126d21ff0edSHermès Bélusca-Maïto { 1127c2c66affSColin Finck return FALSE; 1128d21ff0edSHermès Bélusca-Maïto } 1129c2c66affSColin Finck 1130c2c66affSColin Finck if (!NT_SUCCESS(KdbpSafeReadMemory(&Ebp, 1131c2c66affSColin Finck (PVOID)&Tss->Ebp, 1132c2c66affSColin Finck sizeof(ULONG_PTR)))) 1133d21ff0edSHermès Bélusca-Maïto { 1134c2c66affSColin Finck return FALSE; 1135d21ff0edSHermès Bélusca-Maïto } 1136c2c66affSColin Finck 1137d21ff0edSHermès Bélusca-Maïto /* Return the parent TSS and its trap frame */ 1138d21ff0edSHermès Bélusca-Maïto *TssSelector = Backlink; 1139d21ff0edSHermès Bélusca-Maïto *pTss = Tss; 1140baa47fa5SHervé Poussineau Context->Eip = Eip; 1141baa47fa5SHervé Poussineau Context->Ebp = Ebp; 1142c2c66affSColin Finck return TRUE; 1143c2c66affSColin Finck } 11443726b992SJérôme Gardou #endif 1145c2c66affSColin Finck 1146c2c66affSColin Finck /*!\brief Displays a backtrace. 1147c2c66affSColin Finck */ 1148c2c66affSColin Finck static BOOLEAN 1149c2c66affSColin Finck KdbpCmdBackTrace( 1150c2c66affSColin Finck ULONG Argc, 1151c2c66affSColin Finck PCHAR Argv[]) 1152c2c66affSColin Finck { 1153c2c66affSColin Finck ULONG ul; 1154c2c66affSColin Finck ULONGLONG Result = 0; 1155baa47fa5SHervé Poussineau CONTEXT Context = *KdbCurrentTrapFrame; 11563726b992SJérôme Gardou ULONG_PTR Frame = KeGetContextFrameRegister(&Context); 1157c2c66affSColin Finck ULONG_PTR Address; 1158c2c66affSColin Finck 1159c2c66affSColin Finck if (Argc >= 2) 1160c2c66affSColin Finck { 1161c2c66affSColin Finck /* Check for [L count] part */ 1162c2c66affSColin Finck ul = 0; 1163c2c66affSColin Finck if (strcmp(Argv[Argc-2], "L") == 0) 1164c2c66affSColin Finck { 1165c2c66affSColin Finck ul = strtoul(Argv[Argc-1], NULL, 0); 1166c2c66affSColin Finck if (ul > 0) 1167c2c66affSColin Finck { 1168c2c66affSColin Finck Argc -= 2; 1169c2c66affSColin Finck } 1170c2c66affSColin Finck } 1171c2c66affSColin Finck else if (Argv[Argc-1][0] == 'L') 1172c2c66affSColin Finck { 1173c2c66affSColin Finck ul = strtoul(Argv[Argc-1] + 1, NULL, 0); 1174c2c66affSColin Finck if (ul > 0) 1175c2c66affSColin Finck { 1176c2c66affSColin Finck Argc--; 1177c2c66affSColin Finck } 1178c2c66affSColin Finck } 1179c2c66affSColin Finck 1180c2c66affSColin Finck /* Put the remaining arguments back together */ 1181c2c66affSColin Finck Argc--; 1182c2c66affSColin Finck for (ul = 1; ul < Argc; ul++) 1183c2c66affSColin Finck { 1184c2c66affSColin Finck Argv[ul][strlen(Argv[ul])] = ' '; 1185c2c66affSColin Finck } 1186c2c66affSColin Finck Argc++; 1187c2c66affSColin Finck } 1188c2c66affSColin Finck 1189d21ff0edSHermès Bélusca-Maïto /* Check if a Frame Address or Thread ID is given */ 1190c2c66affSColin Finck if (Argc > 1) 1191c2c66affSColin Finck { 1192c2c66affSColin Finck if (Argv[1][0] == '*') 1193c2c66affSColin Finck { 1194c2c66affSColin Finck Argv[1]++; 1195c2c66affSColin Finck 1196c2c66affSColin Finck /* Evaluate the expression */ 1197a890fc64SHermès Bélusca-Maïto if (!KdbpEvaluateExpression(Argv[1], KdbPromptString.Length + (Argv[1]-Argv[0]), &Result)) 1198c2c66affSColin Finck return TRUE; 1199c2c66affSColin Finck 1200c2c66affSColin Finck if (Result > (ULONGLONG)(~((ULONG_PTR)0))) 1201c2c66affSColin Finck KdbpPrint("Warning: Address %I64x is beeing truncated\n", Result); 1202c2c66affSColin Finck 1203c2c66affSColin Finck Frame = (ULONG_PTR)Result; 1204c2c66affSColin Finck } 1205c2c66affSColin Finck else 1206c2c66affSColin Finck { 1207c2c66affSColin Finck KdbpPrint("Thread backtrace not supported yet!\n"); 1208c2c66affSColin Finck return TRUE; 1209c2c66affSColin Finck } 1210c2c66affSColin Finck } 1211d21ff0edSHermès Bélusca-Maïto 12123726b992SJérôme Gardou #ifdef _M_IX86 12133726b992SJérôme Gardou KDESCRIPTOR Gdtr; 12143726b992SJérôme Gardou USHORT TssSelector; 12153726b992SJérôme Gardou PKTSS Tss; 12163726b992SJérôme Gardou 1217d21ff0edSHermès Bélusca-Maïto /* Retrieve the Global Descriptor Table */ 1218d21ff0edSHermès Bélusca-Maïto Ke386GetGlobalDescriptorTable(&Gdtr.Limit); 1219d21ff0edSHermès Bélusca-Maïto 1220d21ff0edSHermès Bélusca-Maïto /* Retrieve the current (active) TSS */ 1221d21ff0edSHermès Bélusca-Maïto TssSelector = Ke386GetTr(); 1222d21ff0edSHermès Bélusca-Maïto Tss = KdbpRetrieveTss(TssSelector, NULL, &Gdtr); 1223d21ff0edSHermès Bélusca-Maïto if (KdbpIsNestedTss(TssSelector, Tss)) 1224d21ff0edSHermès Bélusca-Maïto { 1225d21ff0edSHermès Bélusca-Maïto /* Display the active TSS if it is nested */ 1226d21ff0edSHermès Bélusca-Maïto KdbpPrint("[Active TSS 0x%04x @ 0x%p]\n", TssSelector, Tss); 1227d21ff0edSHermès Bélusca-Maïto } 12283726b992SJérôme Gardou #endif 1229d21ff0edSHermès Bélusca-Maïto 1230d21ff0edSHermès Bélusca-Maïto /* If no Frame Address or Thread ID was given, try printing the function at EIP */ 1231d21ff0edSHermès Bélusca-Maïto if (Argc <= 1) 1232c2c66affSColin Finck { 1233c2c66affSColin Finck KdbpPrint("Eip:\n"); 12343726b992SJérôme Gardou if (!KdbSymPrintAddress((PVOID)KeGetContextPc(&Context), &Context)) 12353726b992SJérôme Gardou KdbpPrint("<%p>\n", KeGetContextPc(&Context)); 1236c2c66affSColin Finck else 1237c2c66affSColin Finck KdbpPrint("\n"); 1238c2c66affSColin Finck } 1239c2c66affSColin Finck 1240d21ff0edSHermès Bélusca-Maïto /* Walk through the frames */ 1241c2c66affSColin Finck KdbpPrint("Frames:\n"); 1242c2c66affSColin Finck for (;;) 1243c2c66affSColin Finck { 1244c2c66affSColin Finck BOOLEAN GotNextFrame; 1245c2c66affSColin Finck 1246c2c66affSColin Finck if (Frame == 0) 1247d21ff0edSHermès Bélusca-Maïto goto CheckForParentTSS; 1248c2c66affSColin Finck 1249d21ff0edSHermès Bélusca-Maïto Address = 0; 1250c2c66affSColin Finck if (!NT_SUCCESS(KdbpSafeReadMemory(&Address, (PVOID)(Frame + sizeof(ULONG_PTR)), sizeof(ULONG_PTR)))) 1251c2c66affSColin Finck { 1252c2c66affSColin Finck KdbpPrint("Couldn't access memory at 0x%p!\n", Frame + sizeof(ULONG_PTR)); 1253d21ff0edSHermès Bélusca-Maïto goto CheckForParentTSS; 1254c2c66affSColin Finck } 1255c2c66affSColin Finck 1256d21ff0edSHermès Bélusca-Maïto if (Address == 0) 1257d21ff0edSHermès Bélusca-Maïto goto CheckForParentTSS; 1258c2c66affSColin Finck 1259d21ff0edSHermès Bélusca-Maïto GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof(ULONG_PTR))); 1260d21ff0edSHermès Bélusca-Maïto if (GotNextFrame) 12613726b992SJérôme Gardou { 12623726b992SJérôme Gardou KeSetContextFrameRegister(&Context, Frame); 12633726b992SJérôme Gardou } 1264d21ff0edSHermès Bélusca-Maïto // else 1265d21ff0edSHermès Bélusca-Maïto // Frame = 0; 1266d21ff0edSHermès Bélusca-Maïto 1267d21ff0edSHermès Bélusca-Maïto /* Print the location of the call instruction (assumed 5 bytes length) */ 1268baa47fa5SHervé Poussineau if (!KdbSymPrintAddress((PVOID)(Address - 5), &Context)) 1269c2c66affSColin Finck KdbpPrint("<%08x>\n", Address); 1270c2c66affSColin Finck else 1271c2c66affSColin Finck KdbpPrint("\n"); 1272c2c66affSColin Finck 1273d21ff0edSHermès Bélusca-Maïto if (KdbOutputAborted) 1274c2c66affSColin Finck break; 1275c2c66affSColin Finck 1276d21ff0edSHermès Bélusca-Maïto if (!GotNextFrame) 1277c2c66affSColin Finck { 1278d21ff0edSHermès Bélusca-Maïto KdbpPrint("Couldn't access memory at 0x%p!\n", Frame); 1279d21ff0edSHermès Bélusca-Maïto goto CheckForParentTSS; // break; 1280d21ff0edSHermès Bélusca-Maïto } 1281d21ff0edSHermès Bélusca-Maïto 1282d21ff0edSHermès Bélusca-Maïto continue; 1283d21ff0edSHermès Bélusca-Maïto 1284d21ff0edSHermès Bélusca-Maïto CheckForParentTSS: 12853726b992SJérôme Gardou #ifndef _M_IX86 12863726b992SJérôme Gardou break; 12873726b992SJérôme Gardou #else 1288d21ff0edSHermès Bélusca-Maïto /* 1289d21ff0edSHermès Bélusca-Maïto * We have ended the stack walking for the current (active) TSS. 1290d21ff0edSHermès Bélusca-Maïto * Check whether this TSS was nested, and if so switch to its parent 1291d21ff0edSHermès Bélusca-Maïto * and walk its stack. 1292d21ff0edSHermès Bélusca-Maïto */ 1293d21ff0edSHermès Bélusca-Maïto if (!KdbpIsNestedTss(TssSelector, Tss)) 1294d21ff0edSHermès Bélusca-Maïto break; // The TSS is not nested, we stop there. 1295d21ff0edSHermès Bélusca-Maïto 1296baa47fa5SHervé Poussineau GotNextFrame = KdbpContextFromPrevTss(&Context, &TssSelector, &Tss, &Gdtr); 1297d21ff0edSHermès Bélusca-Maïto if (!GotNextFrame) 1298c2c66affSColin Finck { 1299d21ff0edSHermès Bélusca-Maïto KdbpPrint("Couldn't access parent TSS 0x%04x\n", Tss->Backlink); 1300d21ff0edSHermès Bélusca-Maïto break; // Cannot retrieve the parent TSS, we stop there. 1301d21ff0edSHermès Bélusca-Maïto } 13023726b992SJérôme Gardou 13033726b992SJérôme Gardou 1304baa47fa5SHervé Poussineau Address = Context.Eip; 1305baa47fa5SHervé Poussineau Frame = Context.Ebp; 1306c2c66affSColin Finck 1307d21ff0edSHermès Bélusca-Maïto KdbpPrint("[Parent TSS 0x%04x @ 0x%p]\n", TssSelector, Tss); 1308d21ff0edSHermès Bélusca-Maïto 1309baa47fa5SHervé Poussineau if (!KdbSymPrintAddress((PVOID)Address, &Context)) 1310c2c66affSColin Finck KdbpPrint("<%08x>\n", Address); 1311c2c66affSColin Finck else 1312c2c66affSColin Finck KdbpPrint("\n"); 13133726b992SJérôme Gardou #endif 1314c2c66affSColin Finck } 1315c2c66affSColin Finck 1316c2c66affSColin Finck return TRUE; 1317c2c66affSColin Finck } 1318c2c66affSColin Finck 1319c2c66affSColin Finck /*!\brief Continues execution of the system/leaves KDB. 1320c2c66affSColin Finck */ 1321c2c66affSColin Finck static BOOLEAN 1322c2c66affSColin Finck KdbpCmdContinue( 1323c2c66affSColin Finck ULONG Argc, 1324c2c66affSColin Finck PCHAR Argv[]) 1325c2c66affSColin Finck { 1326c2c66affSColin Finck /* Exit the main loop */ 1327c2c66affSColin Finck return FALSE; 1328c2c66affSColin Finck } 1329c2c66affSColin Finck 1330c2c66affSColin Finck /*!\brief Continues execution of the system/leaves KDB. 1331c2c66affSColin Finck */ 1332c2c66affSColin Finck static BOOLEAN 1333c2c66affSColin Finck KdbpCmdStep( 1334c2c66affSColin Finck ULONG Argc, 1335c2c66affSColin Finck PCHAR Argv[]) 1336c2c66affSColin Finck { 1337c2c66affSColin Finck ULONG Count = 1; 1338c2c66affSColin Finck 1339c2c66affSColin Finck if (Argc > 1) 1340c2c66affSColin Finck { 1341c2c66affSColin Finck Count = strtoul(Argv[1], NULL, 0); 1342c2c66affSColin Finck if (Count == 0) 1343c2c66affSColin Finck { 1344c2c66affSColin Finck KdbpPrint("%s: Integer argument required\n", Argv[0]); 1345c2c66affSColin Finck return TRUE; 1346c2c66affSColin Finck } 1347c2c66affSColin Finck } 1348c2c66affSColin Finck 1349c2c66affSColin Finck if (Argv[0][0] == 'n') 1350c2c66affSColin Finck KdbSingleStepOver = TRUE; 1351c2c66affSColin Finck else 1352c2c66affSColin Finck KdbSingleStepOver = FALSE; 1353c2c66affSColin Finck 1354c2c66affSColin Finck /* Set the number of single steps and return to the interrupted code. */ 1355c2c66affSColin Finck KdbNumSingleSteps = Count; 1356c2c66affSColin Finck 1357c2c66affSColin Finck return FALSE; 1358c2c66affSColin Finck } 1359c2c66affSColin Finck 1360c2c66affSColin Finck /*!\brief Lists breakpoints. 1361c2c66affSColin Finck */ 1362c2c66affSColin Finck static BOOLEAN 1363c2c66affSColin Finck KdbpCmdBreakPointList( 1364c2c66affSColin Finck ULONG Argc, 1365c2c66affSColin Finck PCHAR Argv[]) 1366c2c66affSColin Finck { 1367c2c66affSColin Finck LONG l; 1368c2c66affSColin Finck ULONG_PTR Address = 0; 1369c2c66affSColin Finck KDB_BREAKPOINT_TYPE Type = 0; 1370c2c66affSColin Finck KDB_ACCESS_TYPE AccessType = 0; 1371c2c66affSColin Finck UCHAR Size = 0; 1372c2c66affSColin Finck UCHAR DebugReg = 0; 1373c2c66affSColin Finck BOOLEAN Enabled = FALSE; 1374c2c66affSColin Finck BOOLEAN Global = FALSE; 1375c2c66affSColin Finck PEPROCESS Process = NULL; 1376c2c66affSColin Finck PCHAR str1, str2, ConditionExpr, GlobalOrLocal; 1377c2c66affSColin Finck CHAR Buffer[20]; 1378c2c66affSColin Finck 1379c2c66affSColin Finck l = KdbpGetNextBreakPointNr(0); 1380c2c66affSColin Finck if (l < 0) 1381c2c66affSColin Finck { 1382c2c66affSColin Finck KdbpPrint("No breakpoints.\n"); 1383c2c66affSColin Finck return TRUE; 1384c2c66affSColin Finck } 1385c2c66affSColin Finck 1386c2c66affSColin Finck KdbpPrint("Breakpoints:\n"); 1387c2c66affSColin Finck do 1388c2c66affSColin Finck { 1389c2c66affSColin Finck if (!KdbpGetBreakPointInfo(l, &Address, &Type, &Size, &AccessType, &DebugReg, 1390c2c66affSColin Finck &Enabled, &Global, &Process, &ConditionExpr)) 1391c2c66affSColin Finck { 1392c2c66affSColin Finck continue; 1393c2c66affSColin Finck } 1394c2c66affSColin Finck 1395c2c66affSColin Finck if (l == KdbLastBreakPointNr) 1396c2c66affSColin Finck { 1397c2c66affSColin Finck str1 = "\x1b[1m*"; 1398c2c66affSColin Finck str2 = "\x1b[0m"; 1399c2c66affSColin Finck } 1400c2c66affSColin Finck else 1401c2c66affSColin Finck { 1402c2c66affSColin Finck str1 = " "; 1403c2c66affSColin Finck str2 = ""; 1404c2c66affSColin Finck } 1405c2c66affSColin Finck 1406c2c66affSColin Finck if (Global) 1407c2c66affSColin Finck { 1408c2c66affSColin Finck GlobalOrLocal = " global"; 1409c2c66affSColin Finck } 1410c2c66affSColin Finck else 1411c2c66affSColin Finck { 1412c2c66affSColin Finck GlobalOrLocal = Buffer; 14133726b992SJérôme Gardou sprintf(Buffer, " PID 0x%lx", 14143726b992SJérôme Gardou (ULONG_PTR)(Process ? Process->UniqueProcessId : INVALID_HANDLE_VALUE)); 1415c2c66affSColin Finck } 1416c2c66affSColin Finck 1417c2c66affSColin Finck if (Type == KdbBreakPointSoftware || Type == KdbBreakPointTemporary) 1418c2c66affSColin Finck { 1419c2c66affSColin Finck KdbpPrint(" %s%03d BPX 0x%08x%s%s%s%s%s\n", 1420c2c66affSColin Finck str1, l, Address, 1421c2c66affSColin Finck Enabled ? "" : " disabled", 1422c2c66affSColin Finck GlobalOrLocal, 1423c2c66affSColin Finck ConditionExpr ? " IF " : "", 1424c2c66affSColin Finck ConditionExpr ? ConditionExpr : "", 1425c2c66affSColin Finck str2); 1426c2c66affSColin Finck } 1427c2c66affSColin Finck else if (Type == KdbBreakPointHardware) 1428c2c66affSColin Finck { 1429c2c66affSColin Finck if (!Enabled) 1430c2c66affSColin Finck { 1431c2c66affSColin Finck KdbpPrint(" %s%03d BPM 0x%08x %-5s %-5s disabled%s%s%s%s\n", str1, l, Address, 1432c2c66affSColin Finck KDB_ACCESS_TYPE_TO_STRING(AccessType), 1433c2c66affSColin Finck Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"), 1434c2c66affSColin Finck GlobalOrLocal, 1435c2c66affSColin Finck ConditionExpr ? " IF " : "", 1436c2c66affSColin Finck ConditionExpr ? ConditionExpr : "", 1437c2c66affSColin Finck str2); 1438c2c66affSColin Finck } 1439c2c66affSColin Finck else 1440c2c66affSColin Finck { 1441c2c66affSColin Finck KdbpPrint(" %s%03d BPM 0x%08x %-5s %-5s DR%d%s%s%s%s\n", str1, l, Address, 1442c2c66affSColin Finck KDB_ACCESS_TYPE_TO_STRING(AccessType), 1443c2c66affSColin Finck Size == 1 ? "byte" : (Size == 2 ? "word" : "dword"), 1444c2c66affSColin Finck DebugReg, 1445c2c66affSColin Finck GlobalOrLocal, 1446c2c66affSColin Finck ConditionExpr ? " IF " : "", 1447c2c66affSColin Finck ConditionExpr ? ConditionExpr : "", 1448c2c66affSColin Finck str2); 1449c2c66affSColin Finck } 1450c2c66affSColin Finck } 1451c2c66affSColin Finck } 1452c2c66affSColin Finck while ((l = KdbpGetNextBreakPointNr(l+1)) >= 0); 1453c2c66affSColin Finck 1454c2c66affSColin Finck return TRUE; 1455c2c66affSColin Finck } 1456c2c66affSColin Finck 1457c2c66affSColin Finck /*!\brief Enables, disables or clears a breakpoint. 1458c2c66affSColin Finck */ 1459c2c66affSColin Finck static BOOLEAN 1460c2c66affSColin Finck KdbpCmdEnableDisableClearBreakPoint( 1461c2c66affSColin Finck ULONG Argc, 1462c2c66affSColin Finck PCHAR Argv[]) 1463c2c66affSColin Finck { 1464c2c66affSColin Finck PCHAR pend; 1465c2c66affSColin Finck ULONG BreakPointNr; 1466c2c66affSColin Finck 1467c2c66affSColin Finck if (Argc < 2) 1468c2c66affSColin Finck { 1469c2c66affSColin Finck KdbpPrint("%s: argument required\n", Argv[0]); 1470c2c66affSColin Finck return TRUE; 1471c2c66affSColin Finck } 1472c2c66affSColin Finck 1473c2c66affSColin Finck pend = Argv[1]; 1474c2c66affSColin Finck BreakPointNr = strtoul(Argv[1], &pend, 0); 1475c2c66affSColin Finck if (pend == Argv[1] || *pend != '\0') 1476c2c66affSColin Finck { 1477c2c66affSColin Finck KdbpPrint("%s: integer argument required\n", Argv[0]); 1478c2c66affSColin Finck return TRUE; 1479c2c66affSColin Finck } 1480c2c66affSColin Finck 1481c2c66affSColin Finck if (Argv[0][1] == 'e') /* enable */ 1482c2c66affSColin Finck { 1483c2c66affSColin Finck KdbpEnableBreakPoint(BreakPointNr, NULL); 1484c2c66affSColin Finck } 1485c2c66affSColin Finck else if (Argv [0][1] == 'd') /* disable */ 1486c2c66affSColin Finck { 1487c2c66affSColin Finck KdbpDisableBreakPoint(BreakPointNr, NULL); 1488c2c66affSColin Finck } 1489c2c66affSColin Finck else /* clear */ 1490c2c66affSColin Finck { 1491c2c66affSColin Finck ASSERT(Argv[0][1] == 'c'); 1492c2c66affSColin Finck KdbpDeleteBreakPoint(BreakPointNr, NULL); 1493c2c66affSColin Finck } 1494c2c66affSColin Finck 1495c2c66affSColin Finck return TRUE; 1496c2c66affSColin Finck } 1497c2c66affSColin Finck 1498c2c66affSColin Finck /*!\brief Sets a software or hardware (memory) breakpoint at the given address. 1499c2c66affSColin Finck */ 1500c2c66affSColin Finck static BOOLEAN 1501c2c66affSColin Finck KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[]) 1502c2c66affSColin Finck { 1503c2c66affSColin Finck ULONGLONG Result = 0; 1504c2c66affSColin Finck ULONG_PTR Address; 1505c2c66affSColin Finck KDB_BREAKPOINT_TYPE Type; 1506c2c66affSColin Finck UCHAR Size = 0; 1507c2c66affSColin Finck KDB_ACCESS_TYPE AccessType = 0; 1508c2c66affSColin Finck ULONG AddressArgIndex, i; 1509c2c66affSColin Finck LONG ConditionArgIndex; 1510c2c66affSColin Finck BOOLEAN Global = TRUE; 1511c2c66affSColin Finck 1512c2c66affSColin Finck if (Argv[0][2] == 'x') /* software breakpoint */ 1513c2c66affSColin Finck { 1514c2c66affSColin Finck if (Argc < 2) 1515c2c66affSColin Finck { 1516c2c66affSColin Finck KdbpPrint("bpx: Address argument required.\n"); 1517c2c66affSColin Finck return TRUE; 1518c2c66affSColin Finck } 1519c2c66affSColin Finck 1520c2c66affSColin Finck AddressArgIndex = 1; 1521c2c66affSColin Finck Type = KdbBreakPointSoftware; 1522c2c66affSColin Finck } 1523c2c66affSColin Finck else /* memory breakpoint */ 1524c2c66affSColin Finck { 1525c2c66affSColin Finck ASSERT(Argv[0][2] == 'm'); 1526c2c66affSColin Finck 1527c2c66affSColin Finck if (Argc < 2) 1528c2c66affSColin Finck { 1529c2c66affSColin Finck KdbpPrint("bpm: Access type argument required (one of r, w, rw, x)\n"); 1530c2c66affSColin Finck return TRUE; 1531c2c66affSColin Finck } 1532c2c66affSColin Finck 1533c2c66affSColin Finck if (_stricmp(Argv[1], "x") == 0) 1534c2c66affSColin Finck AccessType = KdbAccessExec; 1535c2c66affSColin Finck else if (_stricmp(Argv[1], "r") == 0) 1536c2c66affSColin Finck AccessType = KdbAccessRead; 1537c2c66affSColin Finck else if (_stricmp(Argv[1], "w") == 0) 1538c2c66affSColin Finck AccessType = KdbAccessWrite; 1539c2c66affSColin Finck else if (_stricmp(Argv[1], "rw") == 0) 1540c2c66affSColin Finck AccessType = KdbAccessReadWrite; 1541c2c66affSColin Finck else 1542c2c66affSColin Finck { 1543c2c66affSColin Finck KdbpPrint("bpm: Unknown access type '%s'\n", Argv[1]); 1544c2c66affSColin Finck return TRUE; 1545c2c66affSColin Finck } 1546c2c66affSColin Finck 1547c2c66affSColin Finck if (Argc < 3) 1548c2c66affSColin Finck { 1549c2c66affSColin Finck KdbpPrint("bpm: %s argument required.\n", AccessType == KdbAccessExec ? "Address" : "Memory size"); 1550c2c66affSColin Finck return TRUE; 1551c2c66affSColin Finck } 1552c2c66affSColin Finck 1553c2c66affSColin Finck AddressArgIndex = 3; 1554c2c66affSColin Finck if (_stricmp(Argv[2], "byte") == 0) 1555c2c66affSColin Finck Size = 1; 1556c2c66affSColin Finck else if (_stricmp(Argv[2], "word") == 0) 1557c2c66affSColin Finck Size = 2; 1558c2c66affSColin Finck else if (_stricmp(Argv[2], "dword") == 0) 1559c2c66affSColin Finck Size = 4; 1560c2c66affSColin Finck else if (AccessType == KdbAccessExec) 1561c2c66affSColin Finck { 1562c2c66affSColin Finck Size = 1; 1563c2c66affSColin Finck AddressArgIndex--; 1564c2c66affSColin Finck } 1565c2c66affSColin Finck else 1566c2c66affSColin Finck { 1567c2c66affSColin Finck KdbpPrint("bpm: Unknown memory size '%s'\n", Argv[2]); 1568c2c66affSColin Finck return TRUE; 1569c2c66affSColin Finck } 1570c2c66affSColin Finck 1571c2c66affSColin Finck if (Argc <= AddressArgIndex) 1572c2c66affSColin Finck { 1573c2c66affSColin Finck KdbpPrint("bpm: Address argument required.\n"); 1574c2c66affSColin Finck return TRUE; 1575c2c66affSColin Finck } 1576c2c66affSColin Finck 1577c2c66affSColin Finck Type = KdbBreakPointHardware; 1578c2c66affSColin Finck } 1579c2c66affSColin Finck 1580c2c66affSColin Finck /* Put the arguments back together */ 1581c2c66affSColin Finck ConditionArgIndex = -1; 1582c2c66affSColin Finck for (i = AddressArgIndex; i < (Argc-1); i++) 1583c2c66affSColin Finck { 1584c2c66affSColin Finck if (strcmp(Argv[i+1], "IF") == 0) /* IF found */ 1585c2c66affSColin Finck { 1586c2c66affSColin Finck ConditionArgIndex = i + 2; 1587c2c66affSColin Finck if ((ULONG)ConditionArgIndex >= Argc) 1588c2c66affSColin Finck { 1589c2c66affSColin Finck KdbpPrint("%s: IF requires condition expression.\n", Argv[0]); 1590c2c66affSColin Finck return TRUE; 1591c2c66affSColin Finck } 1592c2c66affSColin Finck 1593c2c66affSColin Finck for (i = ConditionArgIndex; i < (Argc-1); i++) 1594c2c66affSColin Finck Argv[i][strlen(Argv[i])] = ' '; 1595c2c66affSColin Finck 1596c2c66affSColin Finck break; 1597c2c66affSColin Finck } 1598c2c66affSColin Finck 1599c2c66affSColin Finck Argv[i][strlen(Argv[i])] = ' '; 1600c2c66affSColin Finck } 1601c2c66affSColin Finck 1602c2c66affSColin Finck /* Evaluate the address expression */ 1603c2c66affSColin Finck if (!KdbpEvaluateExpression(Argv[AddressArgIndex], 1604a890fc64SHermès Bélusca-Maïto KdbPromptString.Length + (Argv[AddressArgIndex]-Argv[0]), 1605c2c66affSColin Finck &Result)) 1606c2c66affSColin Finck { 1607c2c66affSColin Finck return TRUE; 1608c2c66affSColin Finck } 1609c2c66affSColin Finck 1610c2c66affSColin Finck if (Result > (ULONGLONG)(~((ULONG_PTR)0))) 1611c2c66affSColin Finck KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result); 1612c2c66affSColin Finck 1613c2c66affSColin Finck Address = (ULONG_PTR)Result; 1614c2c66affSColin Finck 1615c2c66affSColin Finck KdbpInsertBreakPoint(Address, Type, Size, AccessType, 1616c2c66affSColin Finck (ConditionArgIndex < 0) ? NULL : Argv[ConditionArgIndex], 1617c2c66affSColin Finck Global, NULL); 1618c2c66affSColin Finck 1619c2c66affSColin Finck return TRUE; 1620c2c66affSColin Finck } 1621c2c66affSColin Finck 1622c2c66affSColin Finck /*!\brief Lists threads or switches to another thread context. 1623c2c66affSColin Finck */ 1624c2c66affSColin Finck static BOOLEAN 1625c2c66affSColin Finck KdbpCmdThread( 1626c2c66affSColin Finck ULONG Argc, 1627c2c66affSColin Finck PCHAR Argv[]) 1628c2c66affSColin Finck { 1629c2c66affSColin Finck PLIST_ENTRY Entry; 1630c2c66affSColin Finck PETHREAD Thread = NULL; 1631c2c66affSColin Finck PEPROCESS Process = NULL; 1632c2c66affSColin Finck BOOLEAN ReferencedThread = FALSE, ReferencedProcess = FALSE; 16333726b992SJérôme Gardou PULONG_PTR Stack; 16343726b992SJérôme Gardou PULONG_PTR Frame; 16353726b992SJérôme Gardou ULONG_PTR Pc; 16363726b992SJérôme Gardou ULONG_PTR ul = 0; 1637c2c66affSColin Finck PCHAR State, pend, str1, str2; 1638c2c66affSColin Finck static const PCHAR ThreadStateToString[DeferredReady+1] = 1639c2c66affSColin Finck { 1640c2c66affSColin Finck "Initialized", "Ready", "Running", 1641c2c66affSColin Finck "Standby", "Terminated", "Waiting", 1642c2c66affSColin Finck "Transition", "DeferredReady" 1643c2c66affSColin Finck }; 1644c2c66affSColin Finck 1645c2c66affSColin Finck ASSERT(KdbCurrentProcess); 1646c2c66affSColin Finck 1647c2c66affSColin Finck if (Argc >= 2 && _stricmp(Argv[1], "list") == 0) 1648c2c66affSColin Finck { 1649c2c66affSColin Finck Process = KdbCurrentProcess; 1650c2c66affSColin Finck 1651c2c66affSColin Finck if (Argc >= 3) 1652c2c66affSColin Finck { 16533726b992SJérôme Gardou ul = strtoulptr(Argv[2], &pend, 0); 1654c2c66affSColin Finck if (Argv[2] == pend) 1655c2c66affSColin Finck { 1656c2c66affSColin Finck KdbpPrint("thread: '%s' is not a valid process id!\n", Argv[2]); 1657c2c66affSColin Finck return TRUE; 1658c2c66affSColin Finck } 1659c2c66affSColin Finck 1660c2c66affSColin Finck if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)ul, &Process))) 1661c2c66affSColin Finck { 1662c2c66affSColin Finck KdbpPrint("thread: Invalid process id!\n"); 1663c2c66affSColin Finck return TRUE; 1664c2c66affSColin Finck } 1665c2c66affSColin Finck 1666c2c66affSColin Finck /* Remember our reference */ 1667c2c66affSColin Finck ReferencedProcess = TRUE; 1668c2c66affSColin Finck } 1669c2c66affSColin Finck 1670c2c66affSColin Finck Entry = Process->ThreadListHead.Flink; 1671c2c66affSColin Finck if (Entry == &Process->ThreadListHead) 1672c2c66affSColin Finck { 1673c2c66affSColin Finck if (Argc >= 3) 16743726b992SJérôme Gardou KdbpPrint("No threads in process 0x%px!\n", (PVOID)ul); 1675c2c66affSColin Finck else 1676c2c66affSColin Finck KdbpPrint("No threads in current process!\n"); 1677c2c66affSColin Finck 1678c2c66affSColin Finck if (ReferencedProcess) 1679c2c66affSColin Finck ObDereferenceObject(Process); 1680c2c66affSColin Finck 1681c2c66affSColin Finck return TRUE; 1682c2c66affSColin Finck } 1683c2c66affSColin Finck 1684c2c66affSColin Finck KdbpPrint(" TID State Prior. Affinity EBP EIP\n"); 1685c2c66affSColin Finck do 1686c2c66affSColin Finck { 1687c2c66affSColin Finck Thread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry); 1688c2c66affSColin Finck 1689c2c66affSColin Finck if (Thread == KdbCurrentThread) 1690c2c66affSColin Finck { 1691c2c66affSColin Finck str1 = "\x1b[1m*"; 1692c2c66affSColin Finck str2 = "\x1b[0m"; 1693c2c66affSColin Finck } 1694c2c66affSColin Finck else 1695c2c66affSColin Finck { 1696c2c66affSColin Finck str1 = " "; 1697c2c66affSColin Finck str2 = ""; 1698c2c66affSColin Finck } 1699c2c66affSColin Finck 1700c2c66affSColin Finck if (!Thread->Tcb.InitialStack) 1701c2c66affSColin Finck { 1702c2c66affSColin Finck /* Thread has no kernel stack (probably terminated) */ 17033726b992SJérôme Gardou Stack = Frame = NULL; 17043726b992SJérôme Gardou Pc = 0; 1705c2c66affSColin Finck } 1706c2c66affSColin Finck else if (Thread->Tcb.TrapFrame) 1707c2c66affSColin Finck { 17083726b992SJérôme Gardou Stack = (PULONG_PTR)KeGetTrapFrameStackRegister(Thread->Tcb.TrapFrame); 17093726b992SJérôme Gardou Frame = (PULONG_PTR)KeGetTrapFrameFrameRegister(Thread->Tcb.TrapFrame); 17103726b992SJérôme Gardou Pc = KeGetTrapFramePc(Thread->Tcb.TrapFrame); 1711c2c66affSColin Finck } 1712c2c66affSColin Finck else 1713c2c66affSColin Finck { 17143726b992SJérôme Gardou Stack = (PULONG_PTR)Thread->Tcb.KernelStack; 17153726b992SJérôme Gardou Frame = (PULONG_PTR)Stack[4]; 17163726b992SJérôme Gardou Pc = 0; 1717c2c66affSColin Finck 17183726b992SJérôme Gardou if (Frame) /* FIXME: Should we attach to the process to read Ebp[1]? */ 17193726b992SJérôme Gardou KdbpSafeReadMemory(&Pc, Frame + 1, sizeof(Pc)); 1720c2c66affSColin Finck } 1721c2c66affSColin Finck 1722c2c66affSColin Finck if (Thread->Tcb.State < (DeferredReady + 1)) 1723c2c66affSColin Finck State = ThreadStateToString[Thread->Tcb.State]; 1724c2c66affSColin Finck else 1725c2c66affSColin Finck State = "Unknown"; 1726c2c66affSColin Finck 1727c2c66affSColin Finck KdbpPrint(" %s0x%08x %-11s %3d 0x%08x 0x%08x 0x%08x%s\n", 1728c2c66affSColin Finck str1, 1729c2c66affSColin Finck Thread->Cid.UniqueThread, 1730c2c66affSColin Finck State, 1731c2c66affSColin Finck Thread->Tcb.Priority, 1732c2c66affSColin Finck Thread->Tcb.Affinity, 17333726b992SJérôme Gardou Frame, 17343726b992SJérôme Gardou Pc, 1735c2c66affSColin Finck str2); 1736c2c66affSColin Finck 1737c2c66affSColin Finck Entry = Entry->Flink; 1738c2c66affSColin Finck } 1739c2c66affSColin Finck while (Entry != &Process->ThreadListHead); 1740c2c66affSColin Finck 1741c2c66affSColin Finck /* Release our reference, if any */ 1742c2c66affSColin Finck if (ReferencedProcess) 1743c2c66affSColin Finck ObDereferenceObject(Process); 1744c2c66affSColin Finck } 1745c2c66affSColin Finck else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0) 1746c2c66affSColin Finck { 1747c2c66affSColin Finck if (Argc < 3) 1748c2c66affSColin Finck { 1749c2c66affSColin Finck KdbpPrint("thread attach: thread id argument required!\n"); 1750c2c66affSColin Finck return TRUE; 1751c2c66affSColin Finck } 1752c2c66affSColin Finck 17533726b992SJérôme Gardou ul = strtoulptr(Argv[2], &pend, 0); 1754c2c66affSColin Finck if (Argv[2] == pend) 1755c2c66affSColin Finck { 1756c2c66affSColin Finck KdbpPrint("thread attach: '%s' is not a valid thread id!\n", Argv[2]); 1757c2c66affSColin Finck return TRUE; 1758c2c66affSColin Finck } 1759c2c66affSColin Finck 1760c2c66affSColin Finck if (!KdbpAttachToThread((PVOID)ul)) 1761c2c66affSColin Finck { 1762c2c66affSColin Finck return TRUE; 1763c2c66affSColin Finck } 1764c2c66affSColin Finck 1765c2c66affSColin Finck KdbpPrint("Attached to thread 0x%08x.\n", ul); 1766c2c66affSColin Finck } 1767c2c66affSColin Finck else 1768c2c66affSColin Finck { 1769c2c66affSColin Finck Thread = KdbCurrentThread; 1770c2c66affSColin Finck 1771c2c66affSColin Finck if (Argc >= 2) 1772c2c66affSColin Finck { 17733726b992SJérôme Gardou ul = strtoulptr(Argv[1], &pend, 0); 1774c2c66affSColin Finck if (Argv[1] == pend) 1775c2c66affSColin Finck { 1776c2c66affSColin Finck KdbpPrint("thread: '%s' is not a valid thread id!\n", Argv[1]); 1777c2c66affSColin Finck return TRUE; 1778c2c66affSColin Finck } 1779c2c66affSColin Finck 1780c2c66affSColin Finck if (!NT_SUCCESS(PsLookupThreadByThreadId((PVOID)ul, &Thread))) 1781c2c66affSColin Finck { 1782c2c66affSColin Finck KdbpPrint("thread: Invalid thread id!\n"); 1783c2c66affSColin Finck return TRUE; 1784c2c66affSColin Finck } 1785c2c66affSColin Finck 1786c2c66affSColin Finck /* Remember our reference */ 1787c2c66affSColin Finck ReferencedThread = TRUE; 1788c2c66affSColin Finck } 1789c2c66affSColin Finck 1790c2c66affSColin Finck if (Thread->Tcb.State < (DeferredReady + 1)) 1791c2c66affSColin Finck State = ThreadStateToString[Thread->Tcb.State]; 1792c2c66affSColin Finck else 1793c2c66affSColin Finck State = "Unknown"; 1794c2c66affSColin Finck 1795c2c66affSColin Finck KdbpPrint("%s" 1796c2c66affSColin Finck " TID: 0x%08x\n" 1797c2c66affSColin Finck " State: %s (0x%x)\n" 1798c2c66affSColin Finck " Priority: %d\n" 1799c2c66affSColin Finck " Affinity: 0x%08x\n" 1800c2c66affSColin Finck " Initial Stack: 0x%08x\n" 1801c2c66affSColin Finck " Stack Limit: 0x%08x\n" 1802c2c66affSColin Finck " Stack Base: 0x%08x\n" 1803c2c66affSColin Finck " Kernel Stack: 0x%08x\n" 1804c2c66affSColin Finck " Trap Frame: 0x%08x\n" 1805*b97d5fd2SJérôme Gardou #ifndef _M_AMD64 1806*b97d5fd2SJérôme Gardou " NPX State: %s (0x%x)\n" 1807*b97d5fd2SJérôme Gardou #endif 1808*b97d5fd2SJérôme Gardou , (Argc < 2) ? "Current Thread:\n" : "" 1809*b97d5fd2SJérôme Gardou , Thread->Cid.UniqueThread 1810*b97d5fd2SJérôme Gardou , State, Thread->Tcb.State 1811*b97d5fd2SJérôme Gardou , Thread->Tcb.Priority 1812*b97d5fd2SJérôme Gardou , Thread->Tcb.Affinity 1813*b97d5fd2SJérôme Gardou , Thread->Tcb.InitialStack 1814*b97d5fd2SJérôme Gardou , Thread->Tcb.StackLimit 1815*b97d5fd2SJérôme Gardou , Thread->Tcb.StackBase 1816*b97d5fd2SJérôme Gardou , Thread->Tcb.KernelStack 1817*b97d5fd2SJérôme Gardou , Thread->Tcb.TrapFrame 18183726b992SJérôme Gardou #ifndef _M_AMD64 18193726b992SJérôme Gardou , NPX_STATE_TO_STRING(Thread->Tcb.NpxState), Thread->Tcb.NpxState 18203726b992SJérôme Gardou #endif 18213726b992SJérôme Gardou ); 1822c2c66affSColin Finck 1823c2c66affSColin Finck /* Release our reference if we had one */ 1824c2c66affSColin Finck if (ReferencedThread) 1825c2c66affSColin Finck ObDereferenceObject(Thread); 1826c2c66affSColin Finck } 1827c2c66affSColin Finck 1828c2c66affSColin Finck return TRUE; 1829c2c66affSColin Finck } 1830c2c66affSColin Finck 1831c2c66affSColin Finck /*!\brief Lists processes or switches to another process context. 1832c2c66affSColin Finck */ 1833c2c66affSColin Finck static BOOLEAN 1834c2c66affSColin Finck KdbpCmdProc( 1835c2c66affSColin Finck ULONG Argc, 1836c2c66affSColin Finck PCHAR Argv[]) 1837c2c66affSColin Finck { 1838c2c66affSColin Finck PLIST_ENTRY Entry; 1839c2c66affSColin Finck PEPROCESS Process; 1840c2c66affSColin Finck BOOLEAN ReferencedProcess = FALSE; 1841c2c66affSColin Finck PCHAR State, pend, str1, str2; 18423726b992SJérôme Gardou ULONG_PTR ul; 1843c2c66affSColin Finck extern LIST_ENTRY PsActiveProcessHead; 1844c2c66affSColin Finck 1845c2c66affSColin Finck if (Argc >= 2 && _stricmp(Argv[1], "list") == 0) 1846c2c66affSColin Finck { 1847c2c66affSColin Finck Entry = PsActiveProcessHead.Flink; 1848c2c66affSColin Finck if (!Entry || Entry == &PsActiveProcessHead) 1849c2c66affSColin Finck { 1850c2c66affSColin Finck KdbpPrint("No processes in the system!\n"); 1851c2c66affSColin Finck return TRUE; 1852c2c66affSColin Finck } 1853c2c66affSColin Finck 1854c2c66affSColin Finck KdbpPrint(" PID State Filename\n"); 1855c2c66affSColin Finck do 1856c2c66affSColin Finck { 1857c2c66affSColin Finck Process = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks); 1858c2c66affSColin Finck 1859c2c66affSColin Finck if (Process == KdbCurrentProcess) 1860c2c66affSColin Finck { 1861c2c66affSColin Finck str1 = "\x1b[1m*"; 1862c2c66affSColin Finck str2 = "\x1b[0m"; 1863c2c66affSColin Finck } 1864c2c66affSColin Finck else 1865c2c66affSColin Finck { 1866c2c66affSColin Finck str1 = " "; 1867c2c66affSColin Finck str2 = ""; 1868c2c66affSColin Finck } 1869c2c66affSColin Finck 1870c2c66affSColin Finck State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" : 1871c2c66affSColin Finck ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition")); 1872c2c66affSColin Finck 1873c2c66affSColin Finck KdbpPrint(" %s0x%08x %-10s %s%s\n", 1874c2c66affSColin Finck str1, 1875c2c66affSColin Finck Process->UniqueProcessId, 1876c2c66affSColin Finck State, 1877c2c66affSColin Finck Process->ImageFileName, 1878c2c66affSColin Finck str2); 1879c2c66affSColin Finck 1880c2c66affSColin Finck Entry = Entry->Flink; 1881c2c66affSColin Finck } 1882c2c66affSColin Finck while(Entry != &PsActiveProcessHead); 1883c2c66affSColin Finck } 1884c2c66affSColin Finck else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0) 1885c2c66affSColin Finck { 1886c2c66affSColin Finck if (Argc < 3) 1887c2c66affSColin Finck { 1888c2c66affSColin Finck KdbpPrint("process attach: process id argument required!\n"); 1889c2c66affSColin Finck return TRUE; 1890c2c66affSColin Finck } 1891c2c66affSColin Finck 18923726b992SJérôme Gardou ul = strtoulptr(Argv[2], &pend, 0); 1893c2c66affSColin Finck if (Argv[2] == pend) 1894c2c66affSColin Finck { 1895c2c66affSColin Finck KdbpPrint("process attach: '%s' is not a valid process id!\n", Argv[2]); 1896c2c66affSColin Finck return TRUE; 1897c2c66affSColin Finck } 1898c2c66affSColin Finck 1899c2c66affSColin Finck if (!KdbpAttachToProcess((PVOID)ul)) 1900c2c66affSColin Finck { 1901c2c66affSColin Finck return TRUE; 1902c2c66affSColin Finck } 1903c2c66affSColin Finck 19043726b992SJérôme Gardou KdbpPrint("Attached to process 0x%p, thread 0x%p.\n", (PVOID)ul, 19053726b992SJérôme Gardou KdbCurrentThread->Cid.UniqueThread); 1906c2c66affSColin Finck } 1907c2c66affSColin Finck else 1908c2c66affSColin Finck { 1909c2c66affSColin Finck Process = KdbCurrentProcess; 1910c2c66affSColin Finck 1911c2c66affSColin Finck if (Argc >= 2) 1912c2c66affSColin Finck { 19133726b992SJérôme Gardou ul = strtoulptr(Argv[1], &pend, 0); 1914c2c66affSColin Finck if (Argv[1] == pend) 1915c2c66affSColin Finck { 1916c2c66affSColin Finck KdbpPrint("proc: '%s' is not a valid process id!\n", Argv[1]); 1917c2c66affSColin Finck return TRUE; 1918c2c66affSColin Finck } 1919c2c66affSColin Finck 1920c2c66affSColin Finck if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)ul, &Process))) 1921c2c66affSColin Finck { 1922c2c66affSColin Finck KdbpPrint("proc: Invalid process id!\n"); 1923c2c66affSColin Finck return TRUE; 1924c2c66affSColin Finck } 1925c2c66affSColin Finck 1926c2c66affSColin Finck /* Remember our reference */ 1927c2c66affSColin Finck ReferencedProcess = TRUE; 1928c2c66affSColin Finck } 1929c2c66affSColin Finck 1930c2c66affSColin Finck State = ((Process->Pcb.State == ProcessInMemory) ? "In Memory" : 1931c2c66affSColin Finck ((Process->Pcb.State == ProcessOutOfMemory) ? "Out of Memory" : "In Transition")); 1932c2c66affSColin Finck KdbpPrint("%s" 1933c2c66affSColin Finck " PID: 0x%08x\n" 1934c2c66affSColin Finck " State: %s (0x%x)\n" 1935c2c66affSColin Finck " Image Filename: %s\n", 1936c2c66affSColin Finck (Argc < 2) ? "Current process:\n" : "", 1937c2c66affSColin Finck Process->UniqueProcessId, 1938c2c66affSColin Finck State, Process->Pcb.State, 1939c2c66affSColin Finck Process->ImageFileName); 1940c2c66affSColin Finck 1941c2c66affSColin Finck /* Release our reference, if any */ 1942c2c66affSColin Finck if (ReferencedProcess) 1943c2c66affSColin Finck ObDereferenceObject(Process); 1944c2c66affSColin Finck } 1945c2c66affSColin Finck 1946c2c66affSColin Finck return TRUE; 1947c2c66affSColin Finck } 1948c2c66affSColin Finck 1949c2c66affSColin Finck /*!\brief Lists loaded modules or the one containing the specified address. 1950c2c66affSColin Finck */ 1951c2c66affSColin Finck static BOOLEAN 1952c2c66affSColin Finck KdbpCmdMod( 1953c2c66affSColin Finck ULONG Argc, 1954c2c66affSColin Finck PCHAR Argv[]) 1955c2c66affSColin Finck { 1956c2c66affSColin Finck ULONGLONG Result = 0; 1957c2c66affSColin Finck ULONG_PTR Address; 1958c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY LdrEntry; 1959c2c66affSColin Finck BOOLEAN DisplayOnlyOneModule = FALSE; 1960c2c66affSColin Finck INT i = 0; 1961c2c66affSColin Finck 1962c2c66affSColin Finck if (Argc >= 2) 1963c2c66affSColin Finck { 1964c2c66affSColin Finck /* Put the arguments back together */ 1965c2c66affSColin Finck Argc--; 1966c2c66affSColin Finck while (--Argc >= 1) 1967c2c66affSColin Finck Argv[Argc][strlen(Argv[Argc])] = ' '; 1968c2c66affSColin Finck 1969c2c66affSColin Finck /* Evaluate the expression */ 1970a890fc64SHermès Bélusca-Maïto if (!KdbpEvaluateExpression(Argv[1], KdbPromptString.Length + (Argv[1]-Argv[0]), &Result)) 1971c2c66affSColin Finck { 1972c2c66affSColin Finck return TRUE; 1973c2c66affSColin Finck } 1974c2c66affSColin Finck 1975c2c66affSColin Finck if (Result > (ULONGLONG)(~((ULONG_PTR)0))) 1976c2c66affSColin Finck KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0],Result); 1977c2c66affSColin Finck 1978c2c66affSColin Finck Address = (ULONG_PTR)Result; 1979c2c66affSColin Finck 1980c2c66affSColin Finck if (!KdbpSymFindModule((PVOID)Address, NULL, -1, &LdrEntry)) 1981c2c66affSColin Finck { 1982c2c66affSColin Finck KdbpPrint("No module containing address 0x%p found!\n", Address); 1983c2c66affSColin Finck return TRUE; 1984c2c66affSColin Finck } 1985c2c66affSColin Finck 1986c2c66affSColin Finck DisplayOnlyOneModule = TRUE; 1987c2c66affSColin Finck } 1988c2c66affSColin Finck else 1989c2c66affSColin Finck { 1990c2c66affSColin Finck if (!KdbpSymFindModule(NULL, NULL, 0, &LdrEntry)) 1991c2c66affSColin Finck { 1992c2c66affSColin Finck ULONG_PTR ntoskrnlBase = ((ULONG_PTR)KdbpCmdMod) & 0xfff00000; 1993c2c66affSColin Finck KdbpPrint(" Base Size Name\n"); 1994c2c66affSColin Finck KdbpPrint(" %08x %08x %s\n", ntoskrnlBase, 0, "ntoskrnl.exe"); 1995c2c66affSColin Finck return TRUE; 1996c2c66affSColin Finck } 1997c2c66affSColin Finck 1998c2c66affSColin Finck i = 1; 1999c2c66affSColin Finck } 2000c2c66affSColin Finck 2001c2c66affSColin Finck KdbpPrint(" Base Size Name\n"); 2002c2c66affSColin Finck for (;;) 2003c2c66affSColin Finck { 2004c2c66affSColin Finck KdbpPrint(" %08x %08x %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->BaseDllName); 2005c2c66affSColin Finck 2006c2c66affSColin Finck if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, NULL, i++, &LdrEntry)) 2007c2c66affSColin Finck break; 2008c2c66affSColin Finck } 2009c2c66affSColin Finck 2010c2c66affSColin Finck return TRUE; 2011c2c66affSColin Finck } 2012c2c66affSColin Finck 2013f0d59e74SHermès Bélusca-Maïto /*!\brief Displays GDT, LDT or IDT. 2014c2c66affSColin Finck */ 2015c2c66affSColin Finck static BOOLEAN 2016c2c66affSColin Finck KdbpCmdGdtLdtIdt( 2017c2c66affSColin Finck ULONG Argc, 2018c2c66affSColin Finck PCHAR Argv[]) 2019c2c66affSColin Finck { 2020c2c66affSColin Finck KDESCRIPTOR Reg; 2021c2c66affSColin Finck ULONG SegDesc[2]; 2022c2c66affSColin Finck ULONG SegBase; 2023c2c66affSColin Finck ULONG SegLimit; 2024c2c66affSColin Finck PCHAR SegType; 2025c2c66affSColin Finck USHORT SegSel; 2026c2c66affSColin Finck UCHAR Type, Dpl; 2027c2c66affSColin Finck INT i; 2028c2c66affSColin Finck ULONG ul; 2029c2c66affSColin Finck 2030c2c66affSColin Finck if (Argv[0][0] == 'i') 2031c2c66affSColin Finck { 2032c2c66affSColin Finck /* Read IDTR */ 2033c2c66affSColin Finck __sidt(&Reg.Limit); 2034c2c66affSColin Finck 2035c2c66affSColin Finck if (Reg.Limit < 7) 2036c2c66affSColin Finck { 2037c2c66affSColin Finck KdbpPrint("Interrupt descriptor table is empty.\n"); 2038c2c66affSColin Finck return TRUE; 2039c2c66affSColin Finck } 2040c2c66affSColin Finck 2041c2c66affSColin Finck KdbpPrint("IDT Base: 0x%08x Limit: 0x%04x\n", Reg.Base, Reg.Limit); 2042c2c66affSColin Finck KdbpPrint(" Idx Type Seg. Sel. Offset DPL\n"); 2043c2c66affSColin Finck 2044c2c66affSColin Finck for (i = 0; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8) 2045c2c66affSColin Finck { 20463726b992SJérôme Gardou if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)((ULONG_PTR)Reg.Base + i), sizeof(SegDesc)))) 2047c2c66affSColin Finck { 20483726b992SJérôme Gardou KdbpPrint("Couldn't access memory at 0x%p!\n", (PVOID)((ULONG_PTR)Reg.Base + i)); 2049c2c66affSColin Finck return TRUE; 2050c2c66affSColin Finck } 2051c2c66affSColin Finck 2052c2c66affSColin Finck Dpl = ((SegDesc[1] >> 13) & 3); 2053c2c66affSColin Finck if ((SegDesc[1] & 0x1f00) == 0x0500) /* Task gate */ 2054c2c66affSColin Finck SegType = "TASKGATE"; 2055c2c66affSColin Finck else if ((SegDesc[1] & 0x1fe0) == 0x0e00) /* 32 bit Interrupt gate */ 2056c2c66affSColin Finck SegType = "INTGATE32"; 2057c2c66affSColin Finck else if ((SegDesc[1] & 0x1fe0) == 0x0600) /* 16 bit Interrupt gate */ 2058c2c66affSColin Finck SegType = "INTGATE16"; 2059c2c66affSColin Finck else if ((SegDesc[1] & 0x1fe0) == 0x0f00) /* 32 bit Trap gate */ 2060c2c66affSColin Finck SegType = "TRAPGATE32"; 2061c2c66affSColin Finck else if ((SegDesc[1] & 0x1fe0) == 0x0700) /* 16 bit Trap gate */ 2062c2c66affSColin Finck SegType = "TRAPGATE16"; 2063c2c66affSColin Finck else 2064c2c66affSColin Finck SegType = "UNKNOWN"; 2065c2c66affSColin Finck 2066c2c66affSColin Finck if ((SegDesc[1] & (1 << 15)) == 0) /* not present */ 2067c2c66affSColin Finck { 2068c2c66affSColin Finck KdbpPrint(" %03d %-10s [NP] [NP] %02d\n", 2069c2c66affSColin Finck i / 8, SegType, Dpl); 2070c2c66affSColin Finck } 2071c2c66affSColin Finck else if ((SegDesc[1] & 0x1f00) == 0x0500) /* Task gate */ 2072c2c66affSColin Finck { 2073c2c66affSColin Finck SegSel = SegDesc[0] >> 16; 2074c2c66affSColin Finck KdbpPrint(" %03d %-10s 0x%04x %02d\n", 2075c2c66affSColin Finck i / 8, SegType, SegSel, Dpl); 2076c2c66affSColin Finck } 2077c2c66affSColin Finck else 2078c2c66affSColin Finck { 2079c2c66affSColin Finck SegSel = SegDesc[0] >> 16; 2080c2c66affSColin Finck SegBase = (SegDesc[1] & 0xffff0000) | (SegDesc[0] & 0x0000ffff); 2081c2c66affSColin Finck KdbpPrint(" %03d %-10s 0x%04x 0x%08x %02d\n", 2082c2c66affSColin Finck i / 8, SegType, SegSel, SegBase, Dpl); 2083c2c66affSColin Finck } 2084c2c66affSColin Finck } 2085c2c66affSColin Finck } 2086c2c66affSColin Finck else 2087c2c66affSColin Finck { 2088c2c66affSColin Finck ul = 0; 2089c2c66affSColin Finck 2090c2c66affSColin Finck if (Argv[0][0] == 'g') 2091c2c66affSColin Finck { 2092c2c66affSColin Finck /* Read GDTR */ 2093c2c66affSColin Finck Ke386GetGlobalDescriptorTable(&Reg.Limit); 2094c2c66affSColin Finck i = 8; 2095c2c66affSColin Finck } 2096c2c66affSColin Finck else 2097c2c66affSColin Finck { 2098c2c66affSColin Finck ASSERT(Argv[0][0] == 'l'); 2099c2c66affSColin Finck 2100c2c66affSColin Finck /* Read LDTR */ 21013726b992SJérôme Gardou Ke386GetLocalDescriptorTable(&Reg.Limit); 2102c2c66affSColin Finck Reg.Base = 0; 2103c2c66affSColin Finck i = 0; 2104c2c66affSColin Finck ul = 1 << 2; 2105c2c66affSColin Finck } 2106c2c66affSColin Finck 2107c2c66affSColin Finck if (Reg.Limit < 7) 2108c2c66affSColin Finck { 2109c2c66affSColin Finck KdbpPrint("%s descriptor table is empty.\n", 2110c2c66affSColin Finck Argv[0][0] == 'g' ? "Global" : "Local"); 2111c2c66affSColin Finck return TRUE; 2112c2c66affSColin Finck } 2113c2c66affSColin Finck 2114c2c66affSColin Finck KdbpPrint("%cDT Base: 0x%08x Limit: 0x%04x\n", 2115c2c66affSColin Finck Argv[0][0] == 'g' ? 'G' : 'L', Reg.Base, Reg.Limit); 2116c2c66affSColin Finck KdbpPrint(" Idx Sel. Type Base Limit DPL Attribs\n"); 2117c2c66affSColin Finck 2118c2c66affSColin Finck for (; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8) 2119c2c66affSColin Finck { 21203726b992SJérôme Gardou if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)((ULONG_PTR)Reg.Base + i), sizeof(SegDesc)))) 2121c2c66affSColin Finck { 21223726b992SJérôme Gardou KdbpPrint("Couldn't access memory at 0x%p!\n", (ULONG_PTR)Reg.Base + i); 2123c2c66affSColin Finck return TRUE; 2124c2c66affSColin Finck } 2125c2c66affSColin Finck 2126c2c66affSColin Finck Dpl = ((SegDesc[1] >> 13) & 3); 2127c2c66affSColin Finck Type = ((SegDesc[1] >> 8) & 0xf); 2128c2c66affSColin Finck 2129c2c66affSColin Finck SegBase = SegDesc[0] >> 16; 2130c2c66affSColin Finck SegBase |= (SegDesc[1] & 0xff) << 16; 2131c2c66affSColin Finck SegBase |= SegDesc[1] & 0xff000000; 2132c2c66affSColin Finck SegLimit = SegDesc[0] & 0x0000ffff; 2133c2c66affSColin Finck SegLimit |= (SegDesc[1] >> 16) & 0xf; 2134c2c66affSColin Finck 2135c2c66affSColin Finck if ((SegDesc[1] & (1 << 23)) != 0) 2136c2c66affSColin Finck { 2137c2c66affSColin Finck SegLimit *= 4096; 2138c2c66affSColin Finck SegLimit += 4095; 2139c2c66affSColin Finck } 2140c2c66affSColin Finck else 2141c2c66affSColin Finck { 2142c2c66affSColin Finck SegLimit++; 2143c2c66affSColin Finck } 2144c2c66affSColin Finck 2145c2c66affSColin Finck if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */ 2146c2c66affSColin Finck { 2147c2c66affSColin Finck switch (Type) 2148c2c66affSColin Finck { 2149c2c66affSColin Finck case 1: SegType = "TSS16(Avl)"; break; 2150c2c66affSColin Finck case 2: SegType = "LDT"; break; 2151c2c66affSColin Finck case 3: SegType = "TSS16(Busy)"; break; 2152c2c66affSColin Finck case 4: SegType = "CALLGATE16"; break; 2153c2c66affSColin Finck case 5: SegType = "TASKGATE"; break; 2154c2c66affSColin Finck case 6: SegType = "INTGATE16"; break; 2155c2c66affSColin Finck case 7: SegType = "TRAPGATE16"; break; 2156c2c66affSColin Finck case 9: SegType = "TSS32(Avl)"; break; 2157c2c66affSColin Finck case 11: SegType = "TSS32(Busy)"; break; 2158c2c66affSColin Finck case 12: SegType = "CALLGATE32"; break; 2159c2c66affSColin Finck case 14: SegType = "INTGATE32"; break; 216029f6d029SHermès Bélusca-Maïto case 15: SegType = "TRAPGATE32"; break; 2161c2c66affSColin Finck default: SegType = "UNKNOWN"; break; 2162c2c66affSColin Finck } 2163c2c66affSColin Finck 2164c2c66affSColin Finck if (!(Type >= 1 && Type <= 3) && 2165c2c66affSColin Finck Type != 9 && Type != 11) 2166c2c66affSColin Finck { 2167c2c66affSColin Finck SegBase = 0; 2168c2c66affSColin Finck SegLimit = 0; 2169c2c66affSColin Finck } 2170c2c66affSColin Finck } 2171c2c66affSColin Finck else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */ 2172c2c66affSColin Finck { 2173c2c66affSColin Finck if ((SegDesc[1] & (1 << 22)) != 0) 2174c2c66affSColin Finck SegType = "DATA32"; 2175c2c66affSColin Finck else 2176c2c66affSColin Finck SegType = "DATA16"; 2177c2c66affSColin Finck } 2178c2c66affSColin Finck else /* Code segment */ 2179c2c66affSColin Finck { 2180c2c66affSColin Finck if ((SegDesc[1] & (1 << 22)) != 0) 2181c2c66affSColin Finck SegType = "CODE32"; 2182c2c66affSColin Finck else 2183c2c66affSColin Finck SegType = "CODE16"; 2184c2c66affSColin Finck } 2185c2c66affSColin Finck 218629f6d029SHermès Bélusca-Maïto if ((SegDesc[1] & (1 << 15)) == 0) /* Not present */ 2187c2c66affSColin Finck { 2188c2c66affSColin Finck KdbpPrint(" %03d 0x%04x %-11s [NP] [NP] %02d NP\n", 2189c2c66affSColin Finck i / 8, i | Dpl | ul, SegType, Dpl); 2190c2c66affSColin Finck } 2191c2c66affSColin Finck else 2192c2c66affSColin Finck { 2193c2c66affSColin Finck KdbpPrint(" %03d 0x%04x %-11s 0x%08x 0x%08x %02d ", 2194c2c66affSColin Finck i / 8, i | Dpl | ul, SegType, SegBase, SegLimit, Dpl); 2195c2c66affSColin Finck 2196c2c66affSColin Finck if ((SegDesc[1] & (1 << 12)) == 0) /* System segment */ 2197c2c66affSColin Finck { 2198c2c66affSColin Finck /* FIXME: Display system segment */ 2199c2c66affSColin Finck } 2200c2c66affSColin Finck else if ((SegDesc[1] & (1 << 11)) == 0) /* Data segment */ 2201c2c66affSColin Finck { 2202c2c66affSColin Finck if ((SegDesc[1] & (1 << 10)) != 0) /* Expand-down */ 2203c2c66affSColin Finck KdbpPrint(" E"); 2204c2c66affSColin Finck 2205c2c66affSColin Finck KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/W" : " R"); 2206c2c66affSColin Finck 2207c2c66affSColin Finck if ((SegDesc[1] & (1 << 8)) != 0) 2208c2c66affSColin Finck KdbpPrint(" A"); 2209c2c66affSColin Finck } 2210c2c66affSColin Finck else /* Code segment */ 2211c2c66affSColin Finck { 2212c2c66affSColin Finck if ((SegDesc[1] & (1 << 10)) != 0) /* Conforming */ 2213c2c66affSColin Finck KdbpPrint(" C"); 2214c2c66affSColin Finck 2215c2c66affSColin Finck KdbpPrint((SegDesc[1] & (1 << 9)) ? " R/X" : " X"); 2216c2c66affSColin Finck 2217c2c66affSColin Finck if ((SegDesc[1] & (1 << 8)) != 0) 2218c2c66affSColin Finck KdbpPrint(" A"); 2219c2c66affSColin Finck } 2220c2c66affSColin Finck 2221c2c66affSColin Finck if ((SegDesc[1] & (1 << 20)) != 0) 2222c2c66affSColin Finck KdbpPrint(" AVL"); 2223c2c66affSColin Finck 2224c2c66affSColin Finck KdbpPrint("\n"); 2225c2c66affSColin Finck } 2226c2c66affSColin Finck } 2227c2c66affSColin Finck } 2228c2c66affSColin Finck 2229c2c66affSColin Finck return TRUE; 2230c2c66affSColin Finck } 2231c2c66affSColin Finck 2232c2c66affSColin Finck /*!\brief Displays the KPCR 2233c2c66affSColin Finck */ 2234c2c66affSColin Finck static BOOLEAN 2235c2c66affSColin Finck KdbpCmdPcr( 2236c2c66affSColin Finck ULONG Argc, 2237c2c66affSColin Finck PCHAR Argv[]) 2238c2c66affSColin Finck { 2239c2c66affSColin Finck PKIPCR Pcr = (PKIPCR)KeGetPcr(); 2240c2c66affSColin Finck 224189b44cfaSHermès Bélusca-Maïto KdbpPrint("Current PCR is at 0x%p.\n", Pcr); 2242c2c66affSColin Finck KdbpPrint(" Tib.ExceptionList: 0x%08x\n" 2243c2c66affSColin Finck " Tib.StackBase: 0x%08x\n" 2244c2c66affSColin Finck " Tib.StackLimit: 0x%08x\n" 2245c2c66affSColin Finck " Tib.SubSystemTib: 0x%08x\n" 2246c2c66affSColin Finck " Tib.FiberData/Version: 0x%08x\n" 2247c2c66affSColin Finck " Tib.ArbitraryUserPointer: 0x%08x\n" 2248c2c66affSColin Finck " Tib.Self: 0x%08x\n" 22493726b992SJérôme Gardou #ifdef _M_IX86 2250631a14ffSAmine Khaldi " SelfPcr: 0x%08x\n" 22513726b992SJérôme Gardou #else 22523726b992SJérôme Gardou " Self: 0x%p\n" 22533726b992SJérôme Gardou #endif 2254c2c66affSColin Finck " PCRCB: 0x%08x\n" 2255c2c66affSColin Finck " Irql: 0x%02x\n" 22563726b992SJérôme Gardou #ifdef _M_IX86 2257c2c66affSColin Finck " IRR: 0x%08x\n" 2258c2c66affSColin Finck " IrrActive: 0x%08x\n" 2259c2c66affSColin Finck " IDR: 0x%08x\n" 22603726b992SJérôme Gardou #endif 2261c2c66affSColin Finck " KdVersionBlock: 0x%08x\n" 22623726b992SJérôme Gardou #ifdef _M_IX86 2263c2c66affSColin Finck " IDT: 0x%08x\n" 2264c2c66affSColin Finck " GDT: 0x%08x\n" 2265c2c66affSColin Finck " TSS: 0x%08x\n" 22663726b992SJérôme Gardou #endif 2267c2c66affSColin Finck " MajorVersion: 0x%04x\n" 2268c2c66affSColin Finck " MinorVersion: 0x%04x\n" 22693726b992SJérôme Gardou #ifdef _M_IX86 2270c2c66affSColin Finck " SetMember: 0x%08x\n" 22713726b992SJérôme Gardou #endif 2272c2c66affSColin Finck " StallScaleFactor: 0x%08x\n" 22733726b992SJérôme Gardou #ifdef _M_IX86 2274c2c66affSColin Finck " Number: 0x%02x\n" 22753726b992SJérôme Gardou #endif 2276c2c66affSColin Finck " L2CacheAssociativity: 0x%02x\n" 22773726b992SJérôme Gardou #ifdef _M_IX86 2278c2c66affSColin Finck " VdmAlert: 0x%08x\n" 22793726b992SJérôme Gardou #endif 2280c2c66affSColin Finck " L2CacheSize: 0x%08x\n" 22813726b992SJérôme Gardou #ifdef _M_IX86 22823726b992SJérôme Gardou " InterruptMode: 0x%08x\n" 22833726b992SJérôme Gardou #endif 22843726b992SJérôme Gardou , Pcr->NtTib.ExceptionList, Pcr->NtTib.StackBase, Pcr->NtTib.StackLimit, 2285c2c66affSColin Finck Pcr->NtTib.SubSystemTib, Pcr->NtTib.FiberData, Pcr->NtTib.ArbitraryUserPointer, 22863726b992SJérôme Gardou Pcr->NtTib.Self 22873726b992SJérôme Gardou #ifdef _M_IX86 22883726b992SJérôme Gardou , Pcr->SelfPcr 22893726b992SJérôme Gardou #else 22903726b992SJérôme Gardou , Pcr->Self 22913726b992SJérôme Gardou #endif 22923726b992SJérôme Gardou , Pcr->Prcb, Pcr->Irql 22933726b992SJérôme Gardou #ifdef _M_IX86 22943726b992SJérôme Gardou , Pcr->IRR, Pcr->IrrActive , Pcr->IDR 22953726b992SJérôme Gardou #endif 22963726b992SJérôme Gardou , Pcr->KdVersionBlock 22973726b992SJérôme Gardou #ifdef _M_IX86 22983726b992SJérôme Gardou , Pcr->IDT, Pcr->GDT, Pcr->TSS 22993726b992SJérôme Gardou #endif 23003726b992SJérôme Gardou , Pcr->MajorVersion, Pcr->MinorVersion 23013726b992SJérôme Gardou #ifdef _M_IX86 23023726b992SJérôme Gardou , Pcr->SetMember 23033726b992SJérôme Gardou #endif 23043726b992SJérôme Gardou , Pcr->StallScaleFactor 23053726b992SJérôme Gardou #ifdef _M_IX86 23063726b992SJérôme Gardou , Pcr->Number 23073726b992SJérôme Gardou #endif 23083726b992SJérôme Gardou , Pcr->SecondLevelCacheAssociativity 23093726b992SJérôme Gardou #ifdef _M_IX86 23103726b992SJérôme Gardou , Pcr->VdmAlert 23113726b992SJérôme Gardou #endif 23123726b992SJérôme Gardou , Pcr->SecondLevelCacheSize 23133726b992SJérôme Gardou #ifdef _M_IX86 23143726b992SJérôme Gardou , Pcr->InterruptMode 23153726b992SJérôme Gardou #endif 23163726b992SJérôme Gardou ); 23173726b992SJérôme Gardou 2318c2c66affSColin Finck 2319c2c66affSColin Finck return TRUE; 2320c2c66affSColin Finck } 2321c2c66affSColin Finck 23223726b992SJérôme Gardou #ifdef _M_IX86 2323c2c66affSColin Finck /*!\brief Displays the TSS 2324c2c66affSColin Finck */ 2325c2c66affSColin Finck static BOOLEAN 2326c2c66affSColin Finck KdbpCmdTss( 2327c2c66affSColin Finck ULONG Argc, 2328c2c66affSColin Finck PCHAR Argv[]) 2329c2c66affSColin Finck { 23308826ee8fSHermès Bélusca-Maïto USHORT TssSelector; 23318826ee8fSHermès Bélusca-Maïto PKTSS Tss = NULL; 2332c2c66affSColin Finck 23338826ee8fSHermès Bélusca-Maïto if (Argc >= 2) 23348826ee8fSHermès Bélusca-Maïto { 23358826ee8fSHermès Bélusca-Maïto /* 23368826ee8fSHermès Bélusca-Maïto * Specified TSS via its selector [selector] or descriptor address [*descaddr]. 23378826ee8fSHermès Bélusca-Maïto * Note that we ignore any other argument values. 23388826ee8fSHermès Bélusca-Maïto */ 23398826ee8fSHermès Bélusca-Maïto PCHAR Param, pszNext; 23408826ee8fSHermès Bélusca-Maïto ULONG ulValue; 23418826ee8fSHermès Bélusca-Maïto 23428826ee8fSHermès Bélusca-Maïto Param = Argv[1]; 23438826ee8fSHermès Bélusca-Maïto if (Argv[1][0] == '*') 23448826ee8fSHermès Bélusca-Maïto ++Param; 23458826ee8fSHermès Bélusca-Maïto 23468826ee8fSHermès Bélusca-Maïto ulValue = strtoul(Param, &pszNext, 0); 23478826ee8fSHermès Bélusca-Maïto if (pszNext && *pszNext) 23488826ee8fSHermès Bélusca-Maïto { 23498826ee8fSHermès Bélusca-Maïto KdbpPrint("Invalid TSS specification.\n"); 23508826ee8fSHermès Bélusca-Maïto return TRUE; 23518826ee8fSHermès Bélusca-Maïto } 23528826ee8fSHermès Bélusca-Maïto 23538826ee8fSHermès Bélusca-Maïto if (Argv[1][0] == '*') 23548826ee8fSHermès Bélusca-Maïto { 23558826ee8fSHermès Bélusca-Maïto /* Descriptor specified */ 23568826ee8fSHermès Bélusca-Maïto TssSelector = 0; // Unknown selector! 23578826ee8fSHermès Bélusca-Maïto // TODO: Room for improvement: Find the TSS descriptor 23588826ee8fSHermès Bélusca-Maïto // in the GDT so as to validate it. 23598826ee8fSHermès Bélusca-Maïto Tss = (PKTSS)(ULONG_PTR)ulValue; 23608826ee8fSHermès Bélusca-Maïto if (!Tss) 23618826ee8fSHermès Bélusca-Maïto { 23628826ee8fSHermès Bélusca-Maïto KdbpPrint("Invalid 32-bit TSS descriptor.\n"); 23638826ee8fSHermès Bélusca-Maïto return TRUE; 23648826ee8fSHermès Bélusca-Maïto } 23658826ee8fSHermès Bélusca-Maïto } 23668826ee8fSHermès Bélusca-Maïto else 23678826ee8fSHermès Bélusca-Maïto { 23688826ee8fSHermès Bélusca-Maïto /* Selector specified, retrive the corresponding TSS */ 23698826ee8fSHermès Bélusca-Maïto TssSelector = (USHORT)ulValue; 23708826ee8fSHermès Bélusca-Maïto Tss = KdbpRetrieveTss(TssSelector, NULL, NULL); 23718826ee8fSHermès Bélusca-Maïto if (!Tss) 23728826ee8fSHermès Bélusca-Maïto { 23738826ee8fSHermès Bélusca-Maïto KdbpPrint("Invalid 32-bit TSS selector.\n"); 23748826ee8fSHermès Bélusca-Maïto return TRUE; 23758826ee8fSHermès Bélusca-Maïto } 23768826ee8fSHermès Bélusca-Maïto } 23778826ee8fSHermès Bélusca-Maïto } 23788826ee8fSHermès Bélusca-Maïto 23798826ee8fSHermès Bélusca-Maïto if (!Tss) 23808826ee8fSHermès Bélusca-Maïto { 23818826ee8fSHermès Bélusca-Maïto /* If no TSS was specified, use the current TSS descriptor */ 23828826ee8fSHermès Bélusca-Maïto TssSelector = Ke386GetTr(); 23838826ee8fSHermès Bélusca-Maïto Tss = KeGetPcr()->TSS; 23848826ee8fSHermès Bélusca-Maïto // NOTE: If everything works OK, Tss is the current TSS corresponding to the TR selector. 23858826ee8fSHermès Bélusca-Maïto } 23868826ee8fSHermès Bélusca-Maïto 23878826ee8fSHermès Bélusca-Maïto KdbpPrint("%s TSS 0x%04x is at 0x%p.\n", 23888826ee8fSHermès Bélusca-Maïto (Tss == KeGetPcr()->TSS) ? "Current" : "Specified", TssSelector, Tss); 23898826ee8fSHermès Bélusca-Maïto KdbpPrint(" Backlink: 0x%04x\n" 23908826ee8fSHermès Bélusca-Maïto " Ss0:Esp0: 0x%04x:0x%08x\n" 23918826ee8fSHermès Bélusca-Maïto // NOTE: Ss1:Esp1 and Ss2:Esp2: are in the NotUsed1 field. 23928826ee8fSHermès Bélusca-Maïto " CR3: 0x%08x\n" 23938826ee8fSHermès Bélusca-Maïto " EFlags: 0x%08x\n" 23948826ee8fSHermès Bélusca-Maïto " Eax: 0x%08x\n" 23958826ee8fSHermès Bélusca-Maïto " Ebx: 0x%08x\n" 23968826ee8fSHermès Bélusca-Maïto " Ecx: 0x%08x\n" 23978826ee8fSHermès Bélusca-Maïto " Edx: 0x%08x\n" 23988826ee8fSHermès Bélusca-Maïto " Esi: 0x%08x\n" 23998826ee8fSHermès Bélusca-Maïto " Edi: 0x%08x\n" 24008826ee8fSHermès Bélusca-Maïto " Eip: 0x%08x\n" 24018826ee8fSHermès Bélusca-Maïto " Esp: 0x%08x\n" 24028826ee8fSHermès Bélusca-Maïto " Ebp: 0x%08x\n" 2403c2c66affSColin Finck " Cs: 0x%04x\n" 2404c2c66affSColin Finck " Ss: 0x%04x\n" 2405c2c66affSColin Finck " Ds: 0x%04x\n" 24068826ee8fSHermès Bélusca-Maïto " Es: 0x%04x\n" 2407c2c66affSColin Finck " Fs: 0x%04x\n" 2408c2c66affSColin Finck " Gs: 0x%04x\n" 24098826ee8fSHermès Bélusca-Maïto " LDT: 0x%04x\n" 24108826ee8fSHermès Bélusca-Maïto " Flags: 0x%04x\n" 2411c2c66affSColin Finck " IoMapBase: 0x%04x\n", 24128826ee8fSHermès Bélusca-Maïto Tss->Backlink, Tss->Ss0, Tss->Esp0, Tss->CR3, Tss->EFlags, 24138826ee8fSHermès Bélusca-Maïto Tss->Eax, Tss->Ebx, Tss->Ecx, Tss->Edx, Tss->Esi, Tss->Edi, 24148826ee8fSHermès Bélusca-Maïto Tss->Eip, Tss->Esp, Tss->Ebp, 24158826ee8fSHermès Bélusca-Maïto Tss->Cs, Tss->Ss, Tss->Ds, Tss->Es, Tss->Fs, Tss->Gs, 24168826ee8fSHermès Bélusca-Maïto Tss->LDT, Tss->Flags, Tss->IoMapBase); 2417c2c66affSColin Finck 2418c2c66affSColin Finck return TRUE; 2419c2c66affSColin Finck } 24203726b992SJérôme Gardou #endif 2421c2c66affSColin Finck 2422c2c66affSColin Finck /*!\brief Bugchecks the system. 2423c2c66affSColin Finck */ 2424c2c66affSColin Finck static BOOLEAN 2425c2c66affSColin Finck KdbpCmdBugCheck( 2426c2c66affSColin Finck ULONG Argc, 2427c2c66affSColin Finck PCHAR Argv[]) 2428c2c66affSColin Finck { 2429c2c66affSColin Finck /* Set the flag and quit looping */ 2430c2c66affSColin Finck KdbpBugCheckRequested = TRUE; 2431c2c66affSColin Finck return FALSE; 2432c2c66affSColin Finck } 2433c2c66affSColin Finck 2434c2c66affSColin Finck static BOOLEAN 2435c2c66affSColin Finck KdbpCmdReboot( 2436c2c66affSColin Finck ULONG Argc, 2437c2c66affSColin Finck PCHAR Argv[]) 2438c2c66affSColin Finck { 2439c2c66affSColin Finck /* Reboot immediately (we do not return) */ 2440c2c66affSColin Finck HalReturnToFirmware(HalRebootRoutine); 2441c2c66affSColin Finck return FALSE; 2442c2c66affSColin Finck } 2443c2c66affSColin Finck 2444c2c66affSColin Finck 2445c2c66affSColin Finck VOID 2446c2c66affSColin Finck KdbpPager( 2447c2c66affSColin Finck IN PCHAR Buffer, 2448c2c66affSColin Finck IN ULONG BufLength); 2449c2c66affSColin Finck 2450c2c66affSColin Finck /*!\brief Display debug messages on screen, with paging. 2451c2c66affSColin Finck * 2452c2c66affSColin Finck * Keys for per-page view: Home, End, PageUp, Arrow Up, PageDown, 2453c2c66affSColin Finck * all others are as PageDown. 2454c2c66affSColin Finck */ 2455c2c66affSColin Finck static BOOLEAN 2456c2c66affSColin Finck KdbpCmdDmesg( 2457c2c66affSColin Finck ULONG Argc, 2458c2c66affSColin Finck PCHAR Argv[]) 2459c2c66affSColin Finck { 2460c2c66affSColin Finck ULONG beg, end; 2461c2c66affSColin Finck 2462c2c66affSColin Finck KdbpIsInDmesgMode = TRUE; /* Toggle logging flag */ 2463c2c66affSColin Finck if (!KdpDmesgBuffer) 2464c2c66affSColin Finck { 2465c2c66affSColin Finck KdbpPrint("Dmesg: error, buffer is not allocated! /DEBUGPORT=SCREEN kernel param required for dmesg.\n"); 2466c2c66affSColin Finck return TRUE; 2467c2c66affSColin Finck } 2468c2c66affSColin Finck 2469c2c66affSColin Finck KdbpPrint("*** Dmesg *** TotalWritten=%lu, BufferSize=%lu, CurrentPosition=%lu\n", 2470c2c66affSColin Finck KdbDmesgTotalWritten, KdpDmesgBufferSize, KdpDmesgCurrentPosition); 2471c2c66affSColin Finck 2472f0d59e74SHermès Bélusca-Maïto /* Pass data to the pager */ 2473c2c66affSColin Finck end = KdpDmesgCurrentPosition; 2474c2c66affSColin Finck beg = (end + KdpDmesgFreeBytes) % KdpDmesgBufferSize; 2475c2c66affSColin Finck 2476f0d59e74SHermès Bélusca-Maïto /* No roll-overs, and overwritten=lost bytes */ 2477c2c66affSColin Finck if (KdbDmesgTotalWritten <= KdpDmesgBufferSize) 2478c2c66affSColin Finck { 2479f0d59e74SHermès Bélusca-Maïto /* Show buffer (KdpDmesgBuffer + beg, num) */ 2480c2c66affSColin Finck KdbpPager(KdpDmesgBuffer, KdpDmesgCurrentPosition); 2481c2c66affSColin Finck } 2482c2c66affSColin Finck else 2483c2c66affSColin Finck { 2484f0d59e74SHermès Bélusca-Maïto /* Show 2 buffers: (KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg) 2485f0d59e74SHermès Bélusca-Maïto * and: (KdpDmesgBuffer, end) */ 2486c2c66affSColin Finck KdbpPager(KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg); 2487c2c66affSColin Finck KdbpPrint("*** Dmesg: buffer rollup ***\n"); 2488c2c66affSColin Finck KdbpPager(KdpDmesgBuffer, end); 2489c2c66affSColin Finck } 2490c2c66affSColin Finck KdbpPrint("*** Dmesg: end of output ***\n"); 2491c2c66affSColin Finck 2492c2c66affSColin Finck KdbpIsInDmesgMode = FALSE; /* Toggle logging flag */ 2493c2c66affSColin Finck 2494c2c66affSColin Finck return TRUE; 2495c2c66affSColin Finck } 2496c2c66affSColin Finck 2497c2c66affSColin Finck /*!\brief Sets or displays a config variables value. 2498c2c66affSColin Finck */ 2499c2c66affSColin Finck static BOOLEAN 2500c2c66affSColin Finck KdbpCmdSet( 2501c2c66affSColin Finck ULONG Argc, 2502c2c66affSColin Finck PCHAR Argv[]) 2503c2c66affSColin Finck { 2504c2c66affSColin Finck LONG l; 2505c2c66affSColin Finck BOOLEAN First; 2506c2c66affSColin Finck PCHAR pend = 0; 2507c2c66affSColin Finck KDB_ENTER_CONDITION ConditionFirst = KdbDoNotEnter; 2508c2c66affSColin Finck KDB_ENTER_CONDITION ConditionLast = KdbDoNotEnter; 2509c2c66affSColin Finck 2510c2c66affSColin Finck static const PCHAR ExceptionNames[21] = 2511c2c66affSColin Finck { 2512c2c66affSColin Finck "ZERODEVIDE", "DEBUGTRAP", "NMI", "INT3", "OVERFLOW", "BOUND", "INVALIDOP", 2513c2c66affSColin Finck "NOMATHCOP", "DOUBLEFAULT", "RESERVED(9)", "INVALIDTSS", "SEGMENTNOTPRESENT", 2514c2c66affSColin Finck "STACKFAULT", "GPF", "PAGEFAULT", "RESERVED(15)", "MATHFAULT", "ALIGNMENTCHECK", 2515c2c66affSColin Finck "MACHINECHECK", "SIMDFAULT", "OTHERS" 2516c2c66affSColin Finck }; 2517c2c66affSColin Finck 2518c2c66affSColin Finck if (Argc == 1) 2519c2c66affSColin Finck { 2520c2c66affSColin Finck KdbpPrint("Available settings:\n"); 2521c2c66affSColin Finck KdbpPrint(" syntax [intel|at&t]\n"); 2522c2c66affSColin Finck KdbpPrint(" condition [exception|*] [first|last] [never|always|kmode|umode]\n"); 2523c2c66affSColin Finck KdbpPrint(" break_on_module_load [true|false]\n"); 2524c2c66affSColin Finck } 2525c2c66affSColin Finck else if (strcmp(Argv[1], "syntax") == 0) 2526c2c66affSColin Finck { 2527c2c66affSColin Finck if (Argc == 2) 2528c2c66affSColin Finck { 2529c2c66affSColin Finck KdbpPrint("syntax = %s\n", KdbUseIntelSyntax ? "intel" : "at&t"); 2530c2c66affSColin Finck } 2531c2c66affSColin Finck else if (Argc >= 3) 2532c2c66affSColin Finck { 2533c2c66affSColin Finck if (_stricmp(Argv[2], "intel") == 0) 2534c2c66affSColin Finck KdbUseIntelSyntax = TRUE; 2535c2c66affSColin Finck else if (_stricmp(Argv[2], "at&t") == 0) 2536c2c66affSColin Finck KdbUseIntelSyntax = FALSE; 2537c2c66affSColin Finck else 2538c2c66affSColin Finck KdbpPrint("Unknown syntax '%s'.\n", Argv[2]); 2539c2c66affSColin Finck } 2540c2c66affSColin Finck } 2541c2c66affSColin Finck else if (strcmp(Argv[1], "condition") == 0) 2542c2c66affSColin Finck { 2543c2c66affSColin Finck if (Argc == 2) 2544c2c66affSColin Finck { 2545c2c66affSColin Finck KdbpPrint("Conditions: (First) (Last)\n"); 2546c2c66affSColin Finck for (l = 0; l < RTL_NUMBER_OF(ExceptionNames) - 1; l++) 2547c2c66affSColin Finck { 2548c2c66affSColin Finck if (!ExceptionNames[l]) 2549c2c66affSColin Finck continue; 2550c2c66affSColin Finck 2551c2c66affSColin Finck if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst)) 2552f0d59e74SHermès Bélusca-Maïto ASSERT(FALSE); 2553c2c66affSColin Finck 2554c2c66affSColin Finck if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast)) 2555f0d59e74SHermès Bélusca-Maïto ASSERT(FALSE); 2556c2c66affSColin Finck 2557c2c66affSColin Finck KdbpPrint(" #%02d %-20s %-8s %-8s\n", l, ExceptionNames[l], 2558c2c66affSColin Finck KDB_ENTER_CONDITION_TO_STRING(ConditionFirst), 2559c2c66affSColin Finck KDB_ENTER_CONDITION_TO_STRING(ConditionLast)); 2560c2c66affSColin Finck } 2561c2c66affSColin Finck 2562c2c66affSColin Finck ASSERT(l == (RTL_NUMBER_OF(ExceptionNames) - 1)); 2563c2c66affSColin Finck KdbpPrint(" %-20s %-8s %-8s\n", ExceptionNames[l], 2564c2c66affSColin Finck KDB_ENTER_CONDITION_TO_STRING(ConditionFirst), 2565c2c66affSColin Finck KDB_ENTER_CONDITION_TO_STRING(ConditionLast)); 2566c2c66affSColin Finck } 2567c2c66affSColin Finck else 2568c2c66affSColin Finck { 2569c2c66affSColin Finck if (Argc >= 5 && strcmp(Argv[2], "*") == 0) /* Allow * only when setting condition */ 2570c2c66affSColin Finck { 2571c2c66affSColin Finck l = -1; 2572c2c66affSColin Finck } 2573c2c66affSColin Finck else 2574c2c66affSColin Finck { 2575c2c66affSColin Finck l = strtoul(Argv[2], &pend, 0); 2576c2c66affSColin Finck 2577c2c66affSColin Finck if (Argv[2] == pend) 2578c2c66affSColin Finck { 2579c2c66affSColin Finck for (l = 0; l < RTL_NUMBER_OF(ExceptionNames); l++) 2580c2c66affSColin Finck { 2581c2c66affSColin Finck if (!ExceptionNames[l]) 2582c2c66affSColin Finck continue; 2583c2c66affSColin Finck 2584c2c66affSColin Finck if (_stricmp(ExceptionNames[l], Argv[2]) == 0) 2585c2c66affSColin Finck break; 2586c2c66affSColin Finck } 2587c2c66affSColin Finck } 2588c2c66affSColin Finck 2589c2c66affSColin Finck if (l >= RTL_NUMBER_OF(ExceptionNames)) 2590c2c66affSColin Finck { 2591c2c66affSColin Finck KdbpPrint("Unknown exception '%s'.\n", Argv[2]); 2592c2c66affSColin Finck return TRUE; 2593c2c66affSColin Finck } 2594c2c66affSColin Finck } 2595c2c66affSColin Finck 2596c2c66affSColin Finck if (Argc > 4) 2597c2c66affSColin Finck { 2598c2c66affSColin Finck if (_stricmp(Argv[3], "first") == 0) 2599c2c66affSColin Finck First = TRUE; 2600c2c66affSColin Finck else if (_stricmp(Argv[3], "last") == 0) 2601c2c66affSColin Finck First = FALSE; 2602c2c66affSColin Finck else 2603c2c66affSColin Finck { 2604c2c66affSColin Finck KdbpPrint("set condition: second argument must be 'first' or 'last'\n"); 2605c2c66affSColin Finck return TRUE; 2606c2c66affSColin Finck } 2607c2c66affSColin Finck 2608c2c66affSColin Finck if (_stricmp(Argv[4], "never") == 0) 2609c2c66affSColin Finck ConditionFirst = KdbDoNotEnter; 2610c2c66affSColin Finck else if (_stricmp(Argv[4], "always") == 0) 2611c2c66affSColin Finck ConditionFirst = KdbEnterAlways; 2612c2c66affSColin Finck else if (_stricmp(Argv[4], "umode") == 0) 2613c2c66affSColin Finck ConditionFirst = KdbEnterFromUmode; 2614c2c66affSColin Finck else if (_stricmp(Argv[4], "kmode") == 0) 2615c2c66affSColin Finck ConditionFirst = KdbEnterFromKmode; 2616c2c66affSColin Finck else 2617c2c66affSColin Finck { 2618c2c66affSColin Finck KdbpPrint("set condition: third argument must be 'never', 'always', 'umode' or 'kmode'\n"); 2619c2c66affSColin Finck return TRUE; 2620c2c66affSColin Finck } 2621c2c66affSColin Finck 2622c2c66affSColin Finck if (!KdbpSetEnterCondition(l, First, ConditionFirst)) 2623c2c66affSColin Finck { 2624c2c66affSColin Finck if (l >= 0) 2625c2c66affSColin Finck KdbpPrint("Couldn't change condition for exception #%02d\n", l); 2626c2c66affSColin Finck else 2627c2c66affSColin Finck KdbpPrint("Couldn't change condition for all exceptions\n", l); 2628c2c66affSColin Finck } 2629c2c66affSColin Finck } 2630c2c66affSColin Finck else /* Argc >= 3 */ 2631c2c66affSColin Finck { 2632c2c66affSColin Finck if (!KdbpGetEnterCondition(l, TRUE, &ConditionFirst)) 2633f0d59e74SHermès Bélusca-Maïto ASSERT(FALSE); 2634c2c66affSColin Finck 2635c2c66affSColin Finck if (!KdbpGetEnterCondition(l, FALSE, &ConditionLast)) 2636f0d59e74SHermès Bélusca-Maïto ASSERT(FALSE); 2637c2c66affSColin Finck 2638c2c66affSColin Finck if (l < (RTL_NUMBER_OF(ExceptionNames) - 1)) 2639c2c66affSColin Finck { 2640c2c66affSColin Finck KdbpPrint("Condition for exception #%02d (%s): FirstChance %s LastChance %s\n", 2641c2c66affSColin Finck l, ExceptionNames[l], 2642c2c66affSColin Finck KDB_ENTER_CONDITION_TO_STRING(ConditionFirst), 2643c2c66affSColin Finck KDB_ENTER_CONDITION_TO_STRING(ConditionLast)); 2644c2c66affSColin Finck } 2645c2c66affSColin Finck else 2646c2c66affSColin Finck { 2647c2c66affSColin Finck KdbpPrint("Condition for all other exceptions: FirstChance %s LastChance %s\n", 2648c2c66affSColin Finck KDB_ENTER_CONDITION_TO_STRING(ConditionFirst), 2649c2c66affSColin Finck KDB_ENTER_CONDITION_TO_STRING(ConditionLast)); 2650c2c66affSColin Finck } 2651c2c66affSColin Finck } 2652c2c66affSColin Finck } 2653c2c66affSColin Finck } 2654c2c66affSColin Finck else if (strcmp(Argv[1], "break_on_module_load") == 0) 2655c2c66affSColin Finck { 2656c2c66affSColin Finck if (Argc == 2) 2657c2c66affSColin Finck KdbpPrint("break_on_module_load = %s\n", KdbBreakOnModuleLoad ? "enabled" : "disabled"); 2658c2c66affSColin Finck else if (Argc >= 3) 2659c2c66affSColin Finck { 2660c2c66affSColin Finck if (_stricmp(Argv[2], "enable") == 0 || _stricmp(Argv[2], "enabled") == 0 || _stricmp(Argv[2], "true") == 0) 2661c2c66affSColin Finck KdbBreakOnModuleLoad = TRUE; 2662c2c66affSColin Finck else if (_stricmp(Argv[2], "disable") == 0 || _stricmp(Argv[2], "disabled") == 0 || _stricmp(Argv[2], "false") == 0) 2663c2c66affSColin Finck KdbBreakOnModuleLoad = FALSE; 2664c2c66affSColin Finck else 2665c2c66affSColin Finck KdbpPrint("Unknown setting '%s'.\n", Argv[2]); 2666c2c66affSColin Finck } 2667c2c66affSColin Finck } 2668c2c66affSColin Finck else 2669c2c66affSColin Finck { 2670c2c66affSColin Finck KdbpPrint("Unknown setting '%s'.\n", Argv[1]); 2671c2c66affSColin Finck } 2672c2c66affSColin Finck 2673c2c66affSColin Finck return TRUE; 2674c2c66affSColin Finck } 2675c2c66affSColin Finck 2676c2c66affSColin Finck /*!\brief Displays help screen. 2677c2c66affSColin Finck */ 2678c2c66affSColin Finck static BOOLEAN 2679c2c66affSColin Finck KdbpCmdHelp( 2680c2c66affSColin Finck ULONG Argc, 2681c2c66affSColin Finck PCHAR Argv[]) 2682c2c66affSColin Finck { 2683c2c66affSColin Finck ULONG i; 2684c2c66affSColin Finck 2685c2c66affSColin Finck KdbpPrint("Kernel debugger commands:\n"); 2686c2c66affSColin Finck for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++) 2687c2c66affSColin Finck { 2688c2c66affSColin Finck if (!KdbDebuggerCommands[i].Syntax) /* Command group */ 2689c2c66affSColin Finck { 2690c2c66affSColin Finck if (i > 0) 2691c2c66affSColin Finck KdbpPrint("\n"); 2692c2c66affSColin Finck 2693c2c66affSColin Finck KdbpPrint("\x1b[7m* %s:\x1b[0m\n", KdbDebuggerCommands[i].Help); 2694c2c66affSColin Finck continue; 2695c2c66affSColin Finck } 2696c2c66affSColin Finck 2697c2c66affSColin Finck KdbpPrint(" %-20s - %s\n", 2698c2c66affSColin Finck KdbDebuggerCommands[i].Syntax, 2699c2c66affSColin Finck KdbDebuggerCommands[i].Help); 2700c2c66affSColin Finck } 2701c2c66affSColin Finck 2702c2c66affSColin Finck return TRUE; 2703c2c66affSColin Finck } 2704c2c66affSColin Finck 2705c2c66affSColin Finck /*!\brief Prints the given string with printf-like formatting. 2706c2c66affSColin Finck * 2707c2c66affSColin Finck * \param Format Format of the string/arguments. 2708c2c66affSColin Finck * \param ... Variable number of arguments matching the format specified in \a Format. 2709c2c66affSColin Finck * 2710c2c66affSColin Finck * \note Doesn't correctly handle \\t and terminal escape sequences when calculating the 2711c2c66affSColin Finck * number of lines required to print a single line from the Buffer in the terminal. 2712c2c66affSColin Finck * Prints maximum 4096 chars, because of its buffer size. 2713c2c66affSColin Finck */ 2714c2c66affSColin Finck VOID 2715c2c66affSColin Finck KdbpPrint( 2716c2c66affSColin Finck IN PCHAR Format, 2717c2c66affSColin Finck IN ... OPTIONAL) 2718c2c66affSColin Finck { 2719c2c66affSColin Finck static CHAR Buffer[4096]; 2720c2c66affSColin Finck static BOOLEAN TerminalInitialized = FALSE; 2721c2c66affSColin Finck static BOOLEAN TerminalConnected = FALSE; 2722c2c66affSColin Finck static BOOLEAN TerminalReportsSize = TRUE; 2723c2c66affSColin Finck CHAR c = '\0'; 2724c2c66affSColin Finck PCHAR p, p2; 2725c2c66affSColin Finck ULONG Length; 2726c2c66affSColin Finck ULONG i, j; 2727c2c66affSColin Finck LONG RowsPrintedByTerminal; 2728c2c66affSColin Finck ULONG ScanCode; 2729c2c66affSColin Finck va_list ap; 2730c2c66affSColin Finck 2731c2c66affSColin Finck /* Check if the user has aborted output of the current command */ 2732c2c66affSColin Finck if (KdbOutputAborted) 2733c2c66affSColin Finck return; 2734c2c66affSColin Finck 2735c2c66affSColin Finck /* Initialize the terminal */ 2736c2c66affSColin Finck if (!TerminalInitialized) 2737c2c66affSColin Finck { 2738c2c66affSColin Finck DbgPrint("\x1b[7h"); /* Enable linewrap */ 2739c2c66affSColin Finck 2740c2c66affSColin Finck /* Query terminal type */ 2741c2c66affSColin Finck /*DbgPrint("\x1b[Z");*/ 2742c2c66affSColin Finck DbgPrint("\x05"); 2743c2c66affSColin Finck 2744c2c66affSColin Finck TerminalInitialized = TRUE; 2745c2c66affSColin Finck Length = 0; 2746c2c66affSColin Finck KeStallExecutionProcessor(100000); 2747c2c66affSColin Finck 2748c2c66affSColin Finck for (;;) 2749c2c66affSColin Finck { 2750c2c66affSColin Finck c = KdbpTryGetCharSerial(5000); 2751c2c66affSColin Finck if (c == -1) 2752c2c66affSColin Finck break; 2753c2c66affSColin Finck 2754c2c66affSColin Finck Buffer[Length++] = c; 2755c2c66affSColin Finck if (Length >= (sizeof(Buffer) - 1)) 2756c2c66affSColin Finck break; 2757c2c66affSColin Finck } 2758c2c66affSColin Finck 2759c2c66affSColin Finck Buffer[Length] = '\0'; 2760c2c66affSColin Finck if (Length > 0) 2761c2c66affSColin Finck TerminalConnected = TRUE; 2762c2c66affSColin Finck } 2763c2c66affSColin Finck 2764c2c66affSColin Finck /* Get number of rows and columns in terminal */ 2765c2c66affSColin Finck if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) || 2766c2c66affSColin Finck (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */ 2767c2c66affSColin Finck { 2768c2c66affSColin Finck if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize) 2769c2c66affSColin Finck { 2770c2c66affSColin Finck /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */ 2771c2c66affSColin Finck TerminalReportsSize = FALSE; 2772c2c66affSColin Finck KeStallExecutionProcessor(100000); 2773c2c66affSColin Finck DbgPrint("\x1b[18t"); 2774c2c66affSColin Finck c = KdbpTryGetCharSerial(5000); 2775c2c66affSColin Finck 2776c2c66affSColin Finck if (c == KEY_ESC) 2777c2c66affSColin Finck { 2778c2c66affSColin Finck c = KdbpTryGetCharSerial(5000); 2779c2c66affSColin Finck if (c == '[') 2780c2c66affSColin Finck { 2781c2c66affSColin Finck Length = 0; 2782c2c66affSColin Finck 2783c2c66affSColin Finck for (;;) 2784c2c66affSColin Finck { 2785c2c66affSColin Finck c = KdbpTryGetCharSerial(5000); 2786c2c66affSColin Finck if (c == -1) 2787c2c66affSColin Finck break; 2788c2c66affSColin Finck 2789c2c66affSColin Finck Buffer[Length++] = c; 2790c2c66affSColin Finck if (isalpha(c) || Length >= (sizeof(Buffer) - 1)) 2791c2c66affSColin Finck break; 2792c2c66affSColin Finck } 2793c2c66affSColin Finck 2794c2c66affSColin Finck Buffer[Length] = '\0'; 2795c2c66affSColin Finck if (Buffer[0] == '8' && Buffer[1] == ';') 2796c2c66affSColin Finck { 2797c2c66affSColin Finck for (i = 2; (i < Length) && (Buffer[i] != ';'); i++); 2798c2c66affSColin Finck 2799c2c66affSColin Finck if (Buffer[i] == ';') 2800c2c66affSColin Finck { 2801c2c66affSColin Finck Buffer[i++] = '\0'; 2802c2c66affSColin Finck 2803c2c66affSColin Finck /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */ 2804c2c66affSColin Finck KdbNumberOfRowsTerminal = strtoul(Buffer + 2, NULL, 0); 2805c2c66affSColin Finck KdbNumberOfColsTerminal = strtoul(Buffer + i, NULL, 0); 2806c2c66affSColin Finck TerminalReportsSize = TRUE; 2807c2c66affSColin Finck } 2808c2c66affSColin Finck } 2809c2c66affSColin Finck } 2810c2c66affSColin Finck /* Clear further characters */ 2811c2c66affSColin Finck while ((c = KdbpTryGetCharSerial(5000)) != -1); 2812c2c66affSColin Finck } 2813c2c66affSColin Finck } 2814c2c66affSColin Finck 2815c2c66affSColin Finck if (KdbNumberOfRowsTerminal <= 0) 2816c2c66affSColin Finck { 2817c2c66affSColin Finck /* Set number of rows to the default. */ 2818c2c66affSColin Finck KdbNumberOfRowsTerminal = 23; //24; //Mna.: 23 for SCREEN debugport 2819c2c66affSColin Finck } 2820c2c66affSColin Finck else if (KdbNumberOfColsTerminal <= 0) 2821c2c66affSColin Finck { 2822c2c66affSColin Finck /* Set number of cols to the default. */ 2823c2c66affSColin Finck KdbNumberOfColsTerminal = 75; //80; //Mna.: 75 for SCREEN debugport 2824c2c66affSColin Finck } 2825c2c66affSColin Finck } 2826c2c66affSColin Finck 2827c2c66affSColin Finck /* Get the string */ 2828c2c66affSColin Finck va_start(ap, Format); 2829c2c66affSColin Finck Length = _vsnprintf(Buffer, sizeof(Buffer) - 1, Format, ap); 2830c2c66affSColin Finck Buffer[Length] = '\0'; 2831c2c66affSColin Finck va_end(ap); 2832c2c66affSColin Finck 2833c2c66affSColin Finck p = Buffer; 2834c2c66affSColin Finck while (p[0] != '\0') 2835c2c66affSColin Finck { 2836c2c66affSColin Finck i = strcspn(p, "\n"); 2837c2c66affSColin Finck 2838c2c66affSColin Finck /* Calculate the number of lines which will be printed in the terminal 2839c2c66affSColin Finck * when outputting the current line 2840c2c66affSColin Finck */ 2841c2c66affSColin Finck if (i > 0) 2842c2c66affSColin Finck RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal; 2843c2c66affSColin Finck else 2844c2c66affSColin Finck RowsPrintedByTerminal = 0; 2845c2c66affSColin Finck 2846c2c66affSColin Finck if (p[i] == '\n') 2847c2c66affSColin Finck RowsPrintedByTerminal++; 2848c2c66affSColin Finck 2849c2c66affSColin Finck /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/ 2850c2c66affSColin Finck 2851c2c66affSColin Finck /* Display a prompt if we printed one screen full of text */ 2852c2c66affSColin Finck if (KdbNumberOfRowsTerminal > 0 && 2853c2c66affSColin Finck (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal) 2854c2c66affSColin Finck { 2855c2c66affSColin Finck KdbRepeatLastCommand = FALSE; 2856c2c66affSColin Finck 2857c2c66affSColin Finck if (KdbNumberOfColsPrinted > 0) 2858c2c66affSColin Finck DbgPrint("\n"); 2859c2c66affSColin Finck 2860c2c66affSColin Finck DbgPrint("--- Press q to abort, any other key to continue ---"); 2861c2c66affSColin Finck RowsPrintedByTerminal++; /* added by Mna. */ 2862c2c66affSColin Finck 2863c2c66affSColin Finck if (KdbDebugState & KD_DEBUG_KDSERIAL) 2864c2c66affSColin Finck c = KdbpGetCharSerial(); 2865c2c66affSColin Finck else 2866c2c66affSColin Finck c = KdbpGetCharKeyboard(&ScanCode); 2867c2c66affSColin Finck 2868c2c66affSColin Finck if (c == '\r') 2869c2c66affSColin Finck { 2870c2c66affSColin Finck /* Try to read '\n' which might follow '\r' - if \n is not received here 2871c2c66affSColin Finck * it will be interpreted as "return" when the next command should be read. 2872c2c66affSColin Finck */ 2873c2c66affSColin Finck if (KdbDebugState & KD_DEBUG_KDSERIAL) 2874c2c66affSColin Finck c = KdbpTryGetCharSerial(5); 2875c2c66affSColin Finck else 2876c2c66affSColin Finck c = KdbpTryGetCharKeyboard(&ScanCode, 5); 2877c2c66affSColin Finck } 2878c2c66affSColin Finck 2879c2c66affSColin Finck DbgPrint("\n"); 2880c2c66affSColin Finck if (c == 'q') 2881c2c66affSColin Finck { 2882c2c66affSColin Finck KdbOutputAborted = TRUE; 2883c2c66affSColin Finck return; 2884c2c66affSColin Finck } 2885c2c66affSColin Finck 2886c2c66affSColin Finck KdbNumberOfRowsPrinted = 0; 2887c2c66affSColin Finck KdbNumberOfColsPrinted = 0; 2888c2c66affSColin Finck } 2889c2c66affSColin Finck 2890c2c66affSColin Finck /* Insert a NUL after the line and print only the current line. */ 2891c2c66affSColin Finck if (p[i] == '\n' && p[i + 1] != '\0') 2892c2c66affSColin Finck { 2893c2c66affSColin Finck c = p[i + 1]; 2894c2c66affSColin Finck p[i + 1] = '\0'; 2895c2c66affSColin Finck } 2896c2c66affSColin Finck else 2897c2c66affSColin Finck { 2898c2c66affSColin Finck c = '\0'; 2899c2c66affSColin Finck } 2900c2c66affSColin Finck 2901c2c66affSColin Finck /* Remove escape sequences from the line if there's no terminal connected */ 2902c2c66affSColin Finck if (!TerminalConnected) 2903c2c66affSColin Finck { 2904c2c66affSColin Finck while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */ 2905c2c66affSColin Finck { 29063af7cb82STimo Kreuzer size_t len = strlen(p2); 2907c2c66affSColin Finck if (p2[1] == '[') 2908c2c66affSColin Finck { 2909c2c66affSColin Finck j = 2; 2910c2c66affSColin Finck while (!isalpha(p2[j++])); 29113af7cb82STimo Kreuzer memmove(p2, p2 + j, len + 1 - j); 2912c2c66affSColin Finck } 2913c2c66affSColin Finck else 2914c2c66affSColin Finck { 29153af7cb82STimo Kreuzer memmove(p2, p2 + 1, len); 2916c2c66affSColin Finck } 2917c2c66affSColin Finck } 2918c2c66affSColin Finck } 2919c2c66affSColin Finck 2920c2c66affSColin Finck DbgPrint("%s", p); 2921c2c66affSColin Finck 2922c2c66affSColin Finck if (c != '\0') 2923c2c66affSColin Finck p[i + 1] = c; 2924c2c66affSColin Finck 2925c2c66affSColin Finck /* Set p to the start of the next line and 2926c2c66affSColin Finck * remember the number of rows/cols printed 2927c2c66affSColin Finck */ 2928c2c66affSColin Finck p += i; 2929c2c66affSColin Finck if (p[0] == '\n') 2930c2c66affSColin Finck { 2931c2c66affSColin Finck p++; 2932c2c66affSColin Finck KdbNumberOfColsPrinted = 0; 2933c2c66affSColin Finck } 2934c2c66affSColin Finck else 2935c2c66affSColin Finck { 2936c2c66affSColin Finck ASSERT(p[0] == '\0'); 2937c2c66affSColin Finck KdbNumberOfColsPrinted += i; 2938c2c66affSColin Finck } 2939c2c66affSColin Finck 2940c2c66affSColin Finck KdbNumberOfRowsPrinted += RowsPrintedByTerminal; 2941c2c66affSColin Finck } 2942c2c66affSColin Finck } 2943c2c66affSColin Finck 2944c2c66affSColin Finck /** memrchr(), explicitly defined, since was absent in MinGW of RosBE. */ 2945c2c66affSColin Finck /* 2946c2c66affSColin Finck * Reverse memchr() 2947c2c66affSColin Finck * Find the last occurrence of 'c' in the buffer 's' of size 'n'. 2948c2c66affSColin Finck */ 2949c2c66affSColin Finck void * 2950c2c66affSColin Finck memrchr(const void *s, int c, size_t n) 2951c2c66affSColin Finck { 2952c2c66affSColin Finck const unsigned char *cp; 2953c2c66affSColin Finck 2954c2c66affSColin Finck if (n != 0) 2955c2c66affSColin Finck { 2956c2c66affSColin Finck cp = (unsigned char *)s + n; 2957c2c66affSColin Finck do 2958c2c66affSColin Finck { 2959c2c66affSColin Finck if (*(--cp) == (unsigned char)c) 2960c2c66affSColin Finck return (void *)cp; 2961c2c66affSColin Finck } while (--n != 0); 2962c2c66affSColin Finck } 2963c2c66affSColin Finck return NULL; 2964c2c66affSColin Finck } 2965c2c66affSColin Finck 2966c2c66affSColin Finck /*!\brief Calculate pointer position for N lines upper of current position. 2967c2c66affSColin Finck * 2968c2c66affSColin Finck * \param Buffer Characters buffer to operate on. 2969c2c66affSColin Finck * \param BufLength Buffer size. 2970c2c66affSColin Finck * 2971c2c66affSColin Finck * \note Calculate pointer position for N lines upper of current displaying 2972c2c66affSColin Finck * position within the given buffer. 2973c2c66affSColin Finck * 2974c2c66affSColin Finck * Used by KdbpPager(). 2975c2c66affSColin Finck * Now N lines count is hardcoded to KdbNumberOfRowsTerminal. 2976c2c66affSColin Finck */ 2977c2c66affSColin Finck PCHAR 2978c2c66affSColin Finck CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos) 2979c2c66affSColin Finck { 2980c2c66affSColin Finck PCHAR p; 2981c2c66affSColin Finck // p0 is initial guess of Page Start 2982c2c66affSColin Finck ULONG p0len = KdbNumberOfRowsTerminal * KdbNumberOfColsTerminal; 2983c2c66affSColin Finck PCHAR p0 = pCurPos - p0len; 2984c2c66affSColin Finck PCHAR prev_p = p0, p1; 2985c2c66affSColin Finck ULONG j; 2986c2c66affSColin Finck 2987c2c66affSColin Finck if (pCurPos < Buffer) 2988c2c66affSColin Finck pCurPos = Buffer; 2989c2c66affSColin Finck ASSERT(pCurPos <= Buffer + BufLength); 2990c2c66affSColin Finck 2991c2c66affSColin Finck p = memrchr(p0, '\n', p0len); 2992c2c66affSColin Finck if (NULL == p) 2993c2c66affSColin Finck p = p0; 2994c2c66affSColin Finck for (j = KdbNumberOfRowsTerminal; j--; ) 2995c2c66affSColin Finck { 2996c2c66affSColin Finck int linesCnt; 2997c2c66affSColin Finck p1 = memrchr(p0, '\n', p-p0); 2998c2c66affSColin Finck prev_p = p; 2999c2c66affSColin Finck p = p1; 3000c2c66affSColin Finck if (NULL == p) 3001c2c66affSColin Finck { 3002c2c66affSColin Finck p = prev_p; 3003c2c66affSColin Finck if (NULL == p) 3004c2c66affSColin Finck p = p0; 3005c2c66affSColin Finck break; 3006c2c66affSColin Finck } 3007c2c66affSColin Finck linesCnt = (KdbNumberOfColsTerminal+prev_p-p-2) / KdbNumberOfColsTerminal; 3008c2c66affSColin Finck if (linesCnt > 1) 3009c2c66affSColin Finck j -= linesCnt-1; 3010c2c66affSColin Finck } 3011c2c66affSColin Finck 3012c2c66affSColin Finck ASSERT(p != 0); 3013c2c66affSColin Finck ++p; 3014c2c66affSColin Finck return p; 3015c2c66affSColin Finck } 3016c2c66affSColin Finck 3017c2c66affSColin Finck /*!\brief Prints the given string with, page by page. 3018c2c66affSColin Finck * 3019c2c66affSColin Finck * \param Buffer Characters buffer to print. 3020c2c66affSColin Finck * \param BufferLen Buffer size. 3021c2c66affSColin Finck * 3022c2c66affSColin Finck * \note Doesn't correctly handle \\t and terminal escape sequences when calculating the 3023c2c66affSColin Finck * number of lines required to print a single line from the Buffer in the terminal. 3024c2c66affSColin Finck * Maximum length of buffer is limited only by memory size. 3025c2c66affSColin Finck * 3026c2c66affSColin Finck * Note: BufLength should be greater then (KdbNumberOfRowsTerminal * KdbNumberOfColsTerminal). 3027c2c66affSColin Finck * 3028c2c66affSColin Finck */ 3029c2c66affSColin Finck VOID 3030c2c66affSColin Finck KdbpPager( 3031c2c66affSColin Finck IN PCHAR Buffer, 3032c2c66affSColin Finck IN ULONG BufLength) 3033c2c66affSColin Finck { 3034c2c66affSColin Finck static CHAR InBuffer[4096]; 3035c2c66affSColin Finck static BOOLEAN TerminalInitialized = FALSE; 3036c2c66affSColin Finck static BOOLEAN TerminalConnected = FALSE; 3037c2c66affSColin Finck static BOOLEAN TerminalReportsSize = TRUE; 3038c2c66affSColin Finck CHAR c = '\0'; 3039c2c66affSColin Finck PCHAR p, p2; 3040c2c66affSColin Finck ULONG Length; 3041c2c66affSColin Finck ULONG i, j; 3042c2c66affSColin Finck LONG RowsPrintedByTerminal; 3043c2c66affSColin Finck ULONG ScanCode; 3044c2c66affSColin Finck 3045c2c66affSColin Finck if( BufLength == 0) 3046c2c66affSColin Finck return; 3047c2c66affSColin Finck 3048c2c66affSColin Finck /* Check if the user has aborted output of the current command */ 3049c2c66affSColin Finck if (KdbOutputAborted) 3050c2c66affSColin Finck return; 3051c2c66affSColin Finck 3052c2c66affSColin Finck /* Initialize the terminal */ 3053c2c66affSColin Finck if (!TerminalInitialized) 3054c2c66affSColin Finck { 3055c2c66affSColin Finck DbgPrint("\x1b[7h"); /* Enable linewrap */ 3056c2c66affSColin Finck 3057c2c66affSColin Finck /* Query terminal type */ 3058c2c66affSColin Finck /*DbgPrint("\x1b[Z");*/ 3059c2c66affSColin Finck DbgPrint("\x05"); 3060c2c66affSColin Finck 3061c2c66affSColin Finck TerminalInitialized = TRUE; 3062c2c66affSColin Finck Length = 0; 3063c2c66affSColin Finck KeStallExecutionProcessor(100000); 3064c2c66affSColin Finck 3065c2c66affSColin Finck for (;;) 3066c2c66affSColin Finck { 3067c2c66affSColin Finck c = KdbpTryGetCharSerial(5000); 3068c2c66affSColin Finck if (c == -1) 3069c2c66affSColin Finck break; 3070c2c66affSColin Finck 3071c2c66affSColin Finck InBuffer[Length++] = c; 3072c2c66affSColin Finck if (Length >= (sizeof(InBuffer) - 1)) 3073c2c66affSColin Finck break; 3074c2c66affSColin Finck } 3075c2c66affSColin Finck 3076c2c66affSColin Finck InBuffer[Length] = '\0'; 3077c2c66affSColin Finck if (Length > 0) 3078c2c66affSColin Finck TerminalConnected = TRUE; 3079c2c66affSColin Finck } 3080c2c66affSColin Finck 3081c2c66affSColin Finck /* Get number of rows and columns in terminal */ 3082c2c66affSColin Finck if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) || 3083c2c66affSColin Finck (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */ 3084c2c66affSColin Finck { 3085c2c66affSColin Finck if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize) 3086c2c66affSColin Finck { 3087c2c66affSColin Finck /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */ 3088c2c66affSColin Finck TerminalReportsSize = FALSE; 3089c2c66affSColin Finck KeStallExecutionProcessor(100000); 3090c2c66affSColin Finck DbgPrint("\x1b[18t"); 3091c2c66affSColin Finck c = KdbpTryGetCharSerial(5000); 3092c2c66affSColin Finck 3093c2c66affSColin Finck if (c == KEY_ESC) 3094c2c66affSColin Finck { 3095c2c66affSColin Finck c = KdbpTryGetCharSerial(5000); 3096c2c66affSColin Finck if (c == '[') 3097c2c66affSColin Finck { 3098c2c66affSColin Finck Length = 0; 3099c2c66affSColin Finck 3100c2c66affSColin Finck for (;;) 3101c2c66affSColin Finck { 3102c2c66affSColin Finck c = KdbpTryGetCharSerial(5000); 3103c2c66affSColin Finck if (c == -1) 3104c2c66affSColin Finck break; 3105c2c66affSColin Finck 3106c2c66affSColin Finck InBuffer[Length++] = c; 3107c2c66affSColin Finck if (isalpha(c) || Length >= (sizeof(InBuffer) - 1)) 3108c2c66affSColin Finck break; 3109c2c66affSColin Finck } 3110c2c66affSColin Finck 3111c2c66affSColin Finck InBuffer[Length] = '\0'; 3112c2c66affSColin Finck if (InBuffer[0] == '8' && InBuffer[1] == ';') 3113c2c66affSColin Finck { 3114c2c66affSColin Finck for (i = 2; (i < Length) && (InBuffer[i] != ';'); i++); 3115c2c66affSColin Finck 3116c2c66affSColin Finck if (Buffer[i] == ';') 3117c2c66affSColin Finck { 3118c2c66affSColin Finck Buffer[i++] = '\0'; 3119c2c66affSColin Finck 3120c2c66affSColin Finck /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */ 3121c2c66affSColin Finck KdbNumberOfRowsTerminal = strtoul(InBuffer + 2, NULL, 0); 3122c2c66affSColin Finck KdbNumberOfColsTerminal = strtoul(InBuffer + i, NULL, 0); 3123c2c66affSColin Finck TerminalReportsSize = TRUE; 3124c2c66affSColin Finck } 3125c2c66affSColin Finck } 3126c2c66affSColin Finck } 3127c2c66affSColin Finck /* Clear further characters */ 3128c2c66affSColin Finck while ((c = KdbpTryGetCharSerial(5000)) != -1); 3129c2c66affSColin Finck } 3130c2c66affSColin Finck } 3131c2c66affSColin Finck 3132c2c66affSColin Finck if (KdbNumberOfRowsTerminal <= 0) 3133c2c66affSColin Finck { 3134c2c66affSColin Finck /* Set number of rows to the default. */ 3135c2c66affSColin Finck KdbNumberOfRowsTerminal = 24; 3136c2c66affSColin Finck } 3137c2c66affSColin Finck else if (KdbNumberOfColsTerminal <= 0) 3138c2c66affSColin Finck { 3139c2c66affSColin Finck /* Set number of cols to the default. */ 3140c2c66affSColin Finck KdbNumberOfColsTerminal = 80; 3141c2c66affSColin Finck } 3142c2c66affSColin Finck } 3143c2c66affSColin Finck 3144c2c66affSColin Finck /* Get the string */ 3145c2c66affSColin Finck p = Buffer; 3146c2c66affSColin Finck 3147c2c66affSColin Finck while (p[0] != '\0') 3148c2c66affSColin Finck { 3149c2c66affSColin Finck if ( p > Buffer+BufLength) 3150c2c66affSColin Finck { 3151c2c66affSColin Finck DbgPrint("Dmesg: error, p > Buffer+BufLength,d=%d", p - (Buffer+BufLength)); 3152c2c66affSColin Finck return; 3153c2c66affSColin Finck } 3154c2c66affSColin Finck i = strcspn(p, "\n"); 3155c2c66affSColin Finck 3156c2c66affSColin Finck // Are we out of buffer? 3157c2c66affSColin Finck if (p + i > Buffer + BufLength) 3158c2c66affSColin Finck // Leaving pager function: 3159c2c66affSColin Finck break; 3160c2c66affSColin Finck 3161c2c66affSColin Finck /* Calculate the number of lines which will be printed in the terminal 3162f0d59e74SHermès Bélusca-Maïto * when outputting the current line. 3163c2c66affSColin Finck */ 3164c2c66affSColin Finck if (i > 0) 3165c2c66affSColin Finck RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal; 3166c2c66affSColin Finck else 3167c2c66affSColin Finck RowsPrintedByTerminal = 0; 3168c2c66affSColin Finck 3169c2c66affSColin Finck if (p[i] == '\n') 3170c2c66affSColin Finck RowsPrintedByTerminal++; 3171c2c66affSColin Finck 3172c2c66affSColin Finck /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/ 3173c2c66affSColin Finck 3174c2c66affSColin Finck /* Display a prompt if we printed one screen full of text */ 3175c2c66affSColin Finck if (KdbNumberOfRowsTerminal > 0 && 3176c2c66affSColin Finck (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal) 3177c2c66affSColin Finck { 3178c2c66affSColin Finck KdbRepeatLastCommand = FALSE; 3179c2c66affSColin Finck 3180c2c66affSColin Finck if (KdbNumberOfColsPrinted > 0) 3181c2c66affSColin Finck DbgPrint("\n"); 3182c2c66affSColin Finck 3183c2c66affSColin Finck DbgPrint("--- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn ---"); 3184c2c66affSColin Finck RowsPrintedByTerminal++; 3185c2c66affSColin Finck 3186c2c66affSColin Finck if (KdbDebugState & KD_DEBUG_KDSERIAL) 3187c2c66affSColin Finck c = KdbpGetCharSerial(); 3188c2c66affSColin Finck else 3189c2c66affSColin Finck c = KdbpGetCharKeyboard(&ScanCode); 3190c2c66affSColin Finck 3191c2c66affSColin Finck if (c == '\r') 3192c2c66affSColin Finck { 3193c2c66affSColin Finck /* Try to read '\n' which might follow '\r' - if \n is not received here 3194c2c66affSColin Finck * it will be interpreted as "return" when the next command should be read. 3195c2c66affSColin Finck */ 3196c2c66affSColin Finck if (KdbDebugState & KD_DEBUG_KDSERIAL) 3197c2c66affSColin Finck c = KdbpTryGetCharSerial(5); 3198c2c66affSColin Finck else 3199c2c66affSColin Finck c = KdbpTryGetCharKeyboard(&ScanCode, 5); 3200c2c66affSColin Finck } 3201c2c66affSColin Finck 3202c2c66affSColin Finck //DbgPrint("\n"); //Consize version: don't show pressed key 3203c2c66affSColin Finck DbgPrint(" '%c'/scan=%04x\n", c, ScanCode); // Shows pressed key 3204c2c66affSColin Finck 3205c2c66affSColin Finck if (c == 'q') 3206c2c66affSColin Finck { 3207c2c66affSColin Finck KdbOutputAborted = TRUE; 3208c2c66affSColin Finck return; 3209c2c66affSColin Finck } 3210c2c66affSColin Finck if ( ScanCode == KEYSC_END || c=='e') 3211c2c66affSColin Finck { 3212c2c66affSColin Finck PCHAR pBufEnd = Buffer + BufLength; 3213c2c66affSColin Finck p = CountOnePageUp(Buffer, BufLength, pBufEnd); 3214c2c66affSColin Finck i = strcspn(p, "\n"); 3215c2c66affSColin Finck } 3216c2c66affSColin Finck else if (ScanCode == KEYSC_PAGEUP || c=='u') 3217c2c66affSColin Finck { 3218c2c66affSColin Finck p = CountOnePageUp(Buffer, BufLength, p); 3219c2c66affSColin Finck i = strcspn(p, "\n"); 3220c2c66affSColin Finck } 3221c2c66affSColin Finck else if (ScanCode == KEYSC_HOME || c=='h') 3222c2c66affSColin Finck { 3223c2c66affSColin Finck p = Buffer; 3224c2c66affSColin Finck i = strcspn(p, "\n"); 3225c2c66affSColin Finck } 3226c2c66affSColin Finck else if (ScanCode == KEYSC_ARROWUP) 3227c2c66affSColin Finck { 3228c2c66affSColin Finck p = CountOnePageUp(Buffer, BufLength, p); 3229c2c66affSColin Finck i = strcspn(p, "\n"); 3230c2c66affSColin Finck } 3231c2c66affSColin Finck 3232c2c66affSColin Finck KdbNumberOfRowsPrinted = 0; 3233c2c66affSColin Finck KdbNumberOfColsPrinted = 0; 3234c2c66affSColin Finck } 3235c2c66affSColin Finck 3236c2c66affSColin Finck /* Insert a NUL after the line and print only the current line. */ 3237c2c66affSColin Finck if (p[i] == '\n' && p[i + 1] != '\0') 3238c2c66affSColin Finck { 3239c2c66affSColin Finck c = p[i + 1]; 3240c2c66affSColin Finck p[i + 1] = '\0'; 3241c2c66affSColin Finck } 3242c2c66affSColin Finck else 3243c2c66affSColin Finck { 3244c2c66affSColin Finck c = '\0'; 3245c2c66affSColin Finck } 3246c2c66affSColin Finck 3247c2c66affSColin Finck /* Remove escape sequences from the line if there's no terminal connected */ 3248c2c66affSColin Finck if (!TerminalConnected) 3249c2c66affSColin Finck { 3250c2c66affSColin Finck while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */ 3251c2c66affSColin Finck { 32523af7cb82STimo Kreuzer size_t len = strlen(p2); 3253c2c66affSColin Finck if (p2[1] == '[') 3254c2c66affSColin Finck { 3255c2c66affSColin Finck j = 2; 3256c2c66affSColin Finck while (!isalpha(p2[j++])); 32573af7cb82STimo Kreuzer memmove(p2, p2 + j, len + 1 - j); 3258c2c66affSColin Finck } 3259c2c66affSColin Finck else 3260c2c66affSColin Finck { 32613af7cb82STimo Kreuzer memmove(p2, p2 + 1, len); 3262c2c66affSColin Finck } 3263c2c66affSColin Finck } 3264c2c66affSColin Finck } 3265c2c66affSColin Finck 3266c2c66affSColin Finck // The main printing of the current line: 3267c2c66affSColin Finck DbgPrint(p); 3268c2c66affSColin Finck 3269c2c66affSColin Finck // restore not null char with saved: 3270c2c66affSColin Finck if (c != '\0') 3271c2c66affSColin Finck p[i + 1] = c; 3272c2c66affSColin Finck 3273c2c66affSColin Finck /* Set p to the start of the next line and 3274c2c66affSColin Finck * remember the number of rows/cols printed 3275c2c66affSColin Finck */ 3276c2c66affSColin Finck p += i; 3277c2c66affSColin Finck if (p[0] == '\n') 3278c2c66affSColin Finck { 3279c2c66affSColin Finck p++; 3280c2c66affSColin Finck KdbNumberOfColsPrinted = 0; 3281c2c66affSColin Finck } 3282c2c66affSColin Finck else 3283c2c66affSColin Finck { 3284c2c66affSColin Finck ASSERT(p[0] == '\0'); 3285c2c66affSColin Finck KdbNumberOfColsPrinted += i; 3286c2c66affSColin Finck } 3287c2c66affSColin Finck 3288c2c66affSColin Finck KdbNumberOfRowsPrinted += RowsPrintedByTerminal; 3289c2c66affSColin Finck } 3290c2c66affSColin Finck } 3291c2c66affSColin Finck 3292c2c66affSColin Finck /*!\brief Appends a command to the command history 3293c2c66affSColin Finck * 3294c2c66affSColin Finck * \param Command Pointer to the command to append to the history. 3295c2c66affSColin Finck */ 3296c2c66affSColin Finck static VOID 3297c2c66affSColin Finck KdbpCommandHistoryAppend( 3298c2c66affSColin Finck IN PCHAR Command) 3299c2c66affSColin Finck { 3300c2c66affSColin Finck ULONG Length1 = strlen(Command) + 1; 3301c2c66affSColin Finck ULONG Length2 = 0; 3302c2c66affSColin Finck INT i; 3303c2c66affSColin Finck PCHAR Buffer; 3304c2c66affSColin Finck 3305c2c66affSColin Finck ASSERT(Length1 <= RTL_NUMBER_OF(KdbCommandHistoryBuffer)); 3306c2c66affSColin Finck 3307c2c66affSColin Finck if (Length1 <= 1 || 3308c2c66affSColin Finck (KdbCommandHistory[KdbCommandHistoryIndex] && 3309c2c66affSColin Finck strcmp(KdbCommandHistory[KdbCommandHistoryIndex], Command) == 0)) 3310c2c66affSColin Finck { 3311c2c66affSColin Finck return; 3312c2c66affSColin Finck } 3313c2c66affSColin Finck 3314c2c66affSColin Finck /* Calculate Length1 and Length2 */ 3315c2c66affSColin Finck Buffer = KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex; 3316c2c66affSColin Finck KdbCommandHistoryBufferIndex += Length1; 3317c2c66affSColin Finck if (KdbCommandHistoryBufferIndex >= (LONG)RTL_NUMBER_OF(KdbCommandHistoryBuffer)) 3318c2c66affSColin Finck { 3319c2c66affSColin Finck KdbCommandHistoryBufferIndex -= RTL_NUMBER_OF(KdbCommandHistoryBuffer); 3320c2c66affSColin Finck Length2 = KdbCommandHistoryBufferIndex; 3321c2c66affSColin Finck Length1 -= Length2; 3322c2c66affSColin Finck } 3323c2c66affSColin Finck 3324c2c66affSColin Finck /* Remove previous commands until there is enough space to append the new command */ 3325c2c66affSColin Finck for (i = KdbCommandHistoryIndex; KdbCommandHistory[i];) 3326c2c66affSColin Finck { 3327c2c66affSColin Finck if ((Length2 > 0 && 3328c2c66affSColin Finck (KdbCommandHistory[i] >= Buffer || 3329c2c66affSColin Finck KdbCommandHistory[i] < (KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex))) || 3330c2c66affSColin Finck (Length2 <= 0 && 3331c2c66affSColin Finck (KdbCommandHistory[i] >= Buffer && 3332c2c66affSColin Finck KdbCommandHistory[i] < (KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex)))) 3333c2c66affSColin Finck { 3334c2c66affSColin Finck KdbCommandHistory[i] = NULL; 3335c2c66affSColin Finck } 3336c2c66affSColin Finck 3337c2c66affSColin Finck i--; 3338c2c66affSColin Finck if (i < 0) 3339c2c66affSColin Finck i = RTL_NUMBER_OF(KdbCommandHistory) - 1; 3340c2c66affSColin Finck 3341c2c66affSColin Finck if (i == KdbCommandHistoryIndex) 3342c2c66affSColin Finck break; 3343c2c66affSColin Finck } 3344c2c66affSColin Finck 3345c2c66affSColin Finck /* Make sure the new command history entry is free */ 3346c2c66affSColin Finck KdbCommandHistoryIndex++; 3347c2c66affSColin Finck KdbCommandHistoryIndex %= RTL_NUMBER_OF(KdbCommandHistory); 3348c2c66affSColin Finck if (KdbCommandHistory[KdbCommandHistoryIndex]) 3349c2c66affSColin Finck { 3350c2c66affSColin Finck KdbCommandHistory[KdbCommandHistoryIndex] = NULL; 3351c2c66affSColin Finck } 3352c2c66affSColin Finck 3353c2c66affSColin Finck /* Append command */ 3354c2c66affSColin Finck KdbCommandHistory[KdbCommandHistoryIndex] = Buffer; 3355c2c66affSColin Finck ASSERT((KdbCommandHistory[KdbCommandHistoryIndex] + Length1) <= KdbCommandHistoryBuffer + RTL_NUMBER_OF(KdbCommandHistoryBuffer)); 3356c2c66affSColin Finck memcpy(KdbCommandHistory[KdbCommandHistoryIndex], Command, Length1); 3357c2c66affSColin Finck if (Length2 > 0) 3358c2c66affSColin Finck { 3359c2c66affSColin Finck memcpy(KdbCommandHistoryBuffer, Command + Length1, Length2); 3360c2c66affSColin Finck } 3361c2c66affSColin Finck } 3362c2c66affSColin Finck 3363c2c66affSColin Finck /*!\brief Reads a line of user-input. 3364c2c66affSColin Finck * 3365c2c66affSColin Finck * \param Buffer Buffer to store the input into. Trailing newlines are removed. 3366c2c66affSColin Finck * \param Size Size of \a Buffer. 3367c2c66affSColin Finck * 3368c2c66affSColin Finck * \note Accepts only \n newlines, \r is ignored. 3369c2c66affSColin Finck */ 3370c2c66affSColin Finck static VOID 3371c2c66affSColin Finck KdbpReadCommand( 3372c2c66affSColin Finck OUT PCHAR Buffer, 3373c2c66affSColin Finck IN ULONG Size) 3374c2c66affSColin Finck { 3375c2c66affSColin Finck CHAR Key; 3376c2c66affSColin Finck PCHAR Orig = Buffer; 3377c2c66affSColin Finck ULONG ScanCode = 0; 3378c2c66affSColin Finck BOOLEAN EchoOn; 3379c2c66affSColin Finck static CHAR LastCommand[1024]; 3380c2c66affSColin Finck static CHAR NextKey = '\0'; 3381c2c66affSColin Finck INT CmdHistIndex = -1; 3382c2c66affSColin Finck INT i; 3383c2c66affSColin Finck 3384c2c66affSColin Finck EchoOn = !((KdbDebugState & KD_DEBUG_KDNOECHO) != 0); 3385c2c66affSColin Finck 3386c2c66affSColin Finck for (;;) 3387c2c66affSColin Finck { 3388c2c66affSColin Finck if (KdbDebugState & KD_DEBUG_KDSERIAL) 3389c2c66affSColin Finck { 3390c2c66affSColin Finck Key = (NextKey == '\0') ? KdbpGetCharSerial() : NextKey; 3391c2c66affSColin Finck NextKey = '\0'; 3392c2c66affSColin Finck ScanCode = 0; 3393c2c66affSColin Finck if (Key == KEY_ESC) /* ESC */ 3394c2c66affSColin Finck { 3395c2c66affSColin Finck Key = KdbpGetCharSerial(); 3396c2c66affSColin Finck if (Key == '[') 3397c2c66affSColin Finck { 3398c2c66affSColin Finck Key = KdbpGetCharSerial(); 3399c2c66affSColin Finck 3400c2c66affSColin Finck switch (Key) 3401c2c66affSColin Finck { 3402c2c66affSColin Finck case 'A': 3403c2c66affSColin Finck ScanCode = KEY_SCAN_UP; 3404c2c66affSColin Finck break; 3405c2c66affSColin Finck case 'B': 3406c2c66affSColin Finck ScanCode = KEY_SCAN_DOWN; 3407c2c66affSColin Finck break; 3408c2c66affSColin Finck case 'C': 3409c2c66affSColin Finck break; 3410c2c66affSColin Finck case 'D': 3411c2c66affSColin Finck break; 3412c2c66affSColin Finck } 3413c2c66affSColin Finck } 3414c2c66affSColin Finck } 3415c2c66affSColin Finck } 3416c2c66affSColin Finck else 3417c2c66affSColin Finck { 3418c2c66affSColin Finck ScanCode = 0; 3419c2c66affSColin Finck Key = (NextKey == '\0') ? KdbpGetCharKeyboard(&ScanCode) : NextKey; 3420c2c66affSColin Finck NextKey = '\0'; 3421c2c66affSColin Finck } 3422c2c66affSColin Finck 3423c2c66affSColin Finck if ((ULONG)(Buffer - Orig) >= (Size - 1)) 3424c2c66affSColin Finck { 3425c2c66affSColin Finck /* Buffer is full, accept only newlines */ 3426c2c66affSColin Finck if (Key != '\n') 3427c2c66affSColin Finck continue; 3428c2c66affSColin Finck } 3429c2c66affSColin Finck 3430c2c66affSColin Finck if (Key == '\r') 3431c2c66affSColin Finck { 3432c2c66affSColin Finck /* Read the next char - this is to throw away a \n which most clients should 3433c2c66affSColin Finck * send after \r. 3434c2c66affSColin Finck */ 3435c2c66affSColin Finck KeStallExecutionProcessor(100000); 3436c2c66affSColin Finck 3437c2c66affSColin Finck if (KdbDebugState & KD_DEBUG_KDSERIAL) 3438c2c66affSColin Finck NextKey = KdbpTryGetCharSerial(5); 3439c2c66affSColin Finck else 3440c2c66affSColin Finck NextKey = KdbpTryGetCharKeyboard(&ScanCode, 5); 3441c2c66affSColin Finck 3442c2c66affSColin Finck if (NextKey == '\n' || NextKey == -1) /* \n or no response at all */ 3443c2c66affSColin Finck NextKey = '\0'; 3444c2c66affSColin Finck 3445c2c66affSColin Finck KdbpPrint("\n"); 3446c2c66affSColin Finck 3447c2c66affSColin Finck /* 3448c2c66affSColin Finck * Repeat the last command if the user presses enter. Reduces the 3449c2c66affSColin Finck * risk of RSI when single-stepping. 3450c2c66affSColin Finck */ 3451c2c66affSColin Finck if (Buffer != Orig) 3452c2c66affSColin Finck { 3453c2c66affSColin Finck KdbRepeatLastCommand = TRUE; 3454c2c66affSColin Finck *Buffer = '\0'; 3455c2c66affSColin Finck RtlStringCbCopyA(LastCommand, sizeof(LastCommand), Orig); 3456c2c66affSColin Finck } 3457c2c66affSColin Finck else if (KdbRepeatLastCommand) 3458c2c66affSColin Finck RtlStringCbCopyA(Buffer, Size, LastCommand); 3459c2c66affSColin Finck else 3460c2c66affSColin Finck *Buffer = '\0'; 3461c2c66affSColin Finck 3462c2c66affSColin Finck return; 3463c2c66affSColin Finck } 3464c2c66affSColin Finck else if (Key == KEY_BS || Key == KEY_DEL) 3465c2c66affSColin Finck { 3466c2c66affSColin Finck if (Buffer > Orig) 3467c2c66affSColin Finck { 3468c2c66affSColin Finck Buffer--; 3469c2c66affSColin Finck *Buffer = 0; 3470c2c66affSColin Finck 3471c2c66affSColin Finck if (EchoOn) 3472c2c66affSColin Finck KdbpPrint("%c %c", KEY_BS, KEY_BS); 3473c2c66affSColin Finck else 3474c2c66affSColin Finck KdbpPrint(" %c", KEY_BS); 3475c2c66affSColin Finck } 3476c2c66affSColin Finck } 3477c2c66affSColin Finck else if (ScanCode == KEY_SCAN_UP) 3478c2c66affSColin Finck { 3479c2c66affSColin Finck BOOLEAN Print = TRUE; 3480c2c66affSColin Finck 3481c2c66affSColin Finck if (CmdHistIndex < 0) 3482c2c66affSColin Finck { 3483c2c66affSColin Finck CmdHistIndex = KdbCommandHistoryIndex; 3484c2c66affSColin Finck } 3485c2c66affSColin Finck else 3486c2c66affSColin Finck { 3487c2c66affSColin Finck i = CmdHistIndex - 1; 3488c2c66affSColin Finck 3489c2c66affSColin Finck if (i < 0) 3490c2c66affSColin Finck CmdHistIndex = RTL_NUMBER_OF(KdbCommandHistory) - 1; 3491c2c66affSColin Finck 3492c2c66affSColin Finck if (KdbCommandHistory[i] && i != KdbCommandHistoryIndex) 3493c2c66affSColin Finck CmdHistIndex = i; 3494c2c66affSColin Finck else 3495c2c66affSColin Finck Print = FALSE; 3496c2c66affSColin Finck } 3497c2c66affSColin Finck 3498c2c66affSColin Finck if (Print && KdbCommandHistory[CmdHistIndex]) 3499c2c66affSColin Finck { 3500c2c66affSColin Finck while (Buffer > Orig) 3501c2c66affSColin Finck { 3502c2c66affSColin Finck Buffer--; 3503c2c66affSColin Finck *Buffer = 0; 3504c2c66affSColin Finck 3505c2c66affSColin Finck if (EchoOn) 3506c2c66affSColin Finck KdbpPrint("%c %c", KEY_BS, KEY_BS); 3507c2c66affSColin Finck else 3508c2c66affSColin Finck KdbpPrint(" %c", KEY_BS); 3509c2c66affSColin Finck } 3510c2c66affSColin Finck 3511c2c66affSColin Finck i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1); 3512c2c66affSColin Finck memcpy(Orig, KdbCommandHistory[CmdHistIndex], i); 3513c2c66affSColin Finck Orig[i] = '\0'; 3514c2c66affSColin Finck Buffer = Orig + i; 3515c2c66affSColin Finck KdbpPrint("%s", Orig); 3516c2c66affSColin Finck } 3517c2c66affSColin Finck } 3518c2c66affSColin Finck else if (ScanCode == KEY_SCAN_DOWN) 3519c2c66affSColin Finck { 3520c2c66affSColin Finck if (CmdHistIndex > 0 && CmdHistIndex != KdbCommandHistoryIndex) 3521c2c66affSColin Finck { 3522c2c66affSColin Finck i = CmdHistIndex + 1; 3523c2c66affSColin Finck if (i >= (INT)RTL_NUMBER_OF(KdbCommandHistory)) 3524c2c66affSColin Finck i = 0; 3525c2c66affSColin Finck 3526c2c66affSColin Finck if (KdbCommandHistory[i]) 3527c2c66affSColin Finck { 3528c2c66affSColin Finck CmdHistIndex = i; 3529c2c66affSColin Finck while (Buffer > Orig) 3530c2c66affSColin Finck { 3531c2c66affSColin Finck Buffer--; 3532c2c66affSColin Finck *Buffer = 0; 3533c2c66affSColin Finck 3534c2c66affSColin Finck if (EchoOn) 3535c2c66affSColin Finck KdbpPrint("%c %c", KEY_BS, KEY_BS); 3536c2c66affSColin Finck else 3537c2c66affSColin Finck KdbpPrint(" %c", KEY_BS); 3538c2c66affSColin Finck } 3539c2c66affSColin Finck 3540c2c66affSColin Finck i = min(strlen(KdbCommandHistory[CmdHistIndex]), Size - 1); 3541c2c66affSColin Finck memcpy(Orig, KdbCommandHistory[CmdHistIndex], i); 3542c2c66affSColin Finck Orig[i] = '\0'; 3543c2c66affSColin Finck Buffer = Orig + i; 3544c2c66affSColin Finck KdbpPrint("%s", Orig); 3545c2c66affSColin Finck } 3546c2c66affSColin Finck } 3547c2c66affSColin Finck } 3548c2c66affSColin Finck else 3549c2c66affSColin Finck { 3550c2c66affSColin Finck if (EchoOn) 3551c2c66affSColin Finck KdbpPrint("%c", Key); 3552c2c66affSColin Finck 3553c2c66affSColin Finck *Buffer = Key; 3554c2c66affSColin Finck Buffer++; 3555c2c66affSColin Finck } 3556c2c66affSColin Finck } 3557c2c66affSColin Finck } 3558c2c66affSColin Finck 3559c2c66affSColin Finck 3560c2c66affSColin Finck BOOLEAN 3561c2c66affSColin Finck NTAPI 3562c2c66affSColin Finck KdbRegisterCliCallback( 3563c2c66affSColin Finck PVOID Callback, 3564c2c66affSColin Finck BOOLEAN Deregister) 3565c2c66affSColin Finck { 3566c2c66affSColin Finck ULONG i; 3567c2c66affSColin Finck 3568c2c66affSColin Finck /* Loop all entries */ 3569c2c66affSColin Finck for (i = 0; i < _countof(KdbCliCallbacks); i++) 3570c2c66affSColin Finck { 3571c2c66affSColin Finck /* Check if deregistering was requested */ 3572c2c66affSColin Finck if (Deregister) 3573c2c66affSColin Finck { 3574c2c66affSColin Finck /* Check if this entry is the one that was registered */ 3575c2c66affSColin Finck if (KdbCliCallbacks[i] == Callback) 3576c2c66affSColin Finck { 3577c2c66affSColin Finck /* Delete it and report success */ 3578c2c66affSColin Finck KdbCliCallbacks[i] = NULL; 3579c2c66affSColin Finck return TRUE; 3580c2c66affSColin Finck } 3581c2c66affSColin Finck } 3582c2c66affSColin Finck else 3583c2c66affSColin Finck { 3584c2c66affSColin Finck /* Check if this entry is free */ 3585c2c66affSColin Finck if (KdbCliCallbacks[i] == NULL) 3586c2c66affSColin Finck { 3587c2c66affSColin Finck /* Set it and and report success */ 3588c2c66affSColin Finck KdbCliCallbacks[i] = Callback; 3589c2c66affSColin Finck return TRUE; 3590c2c66affSColin Finck } 3591c2c66affSColin Finck } 3592c2c66affSColin Finck } 3593c2c66affSColin Finck 3594c2c66affSColin Finck /* Unsuccessful */ 3595c2c66affSColin Finck return FALSE; 3596c2c66affSColin Finck } 3597c2c66affSColin Finck 3598c2c66affSColin Finck /*! \brief Invokes registered CLI callbacks until one of them handled the 3599c2c66affSColin Finck * Command. 3600c2c66affSColin Finck * 3601c2c66affSColin Finck * \param Command - Command line to parse and execute if possible. 3602c2c66affSColin Finck * \param Argc - Number of arguments in Argv 3603c2c66affSColin Finck * \param Argv - Array of strings, each of them containing one argument. 3604c2c66affSColin Finck * 3605c2c66affSColin Finck * \return TRUE, if the command was handled, FALSE if it was not handled. 3606c2c66affSColin Finck */ 3607c2c66affSColin Finck static 3608c2c66affSColin Finck BOOLEAN 3609c2c66affSColin Finck KdbpInvokeCliCallbacks( 3610c2c66affSColin Finck IN PCHAR Command, 3611c2c66affSColin Finck IN ULONG Argc, 361240c57de7SHermès Bélusca-Maïto IN PCHAR Argv[]) 3613c2c66affSColin Finck { 3614c2c66affSColin Finck ULONG i; 3615c2c66affSColin Finck 3616c2c66affSColin Finck /* Loop all entries */ 3617c2c66affSColin Finck for (i = 0; i < _countof(KdbCliCallbacks); i++) 3618c2c66affSColin Finck { 3619c2c66affSColin Finck /* Check if this entry is registered */ 3620c2c66affSColin Finck if (KdbCliCallbacks[i]) 3621c2c66affSColin Finck { 3622c2c66affSColin Finck /* Invoke the callback and check if it handled the command */ 3623c2c66affSColin Finck if (KdbCliCallbacks[i](Command, Argc, Argv)) 3624c2c66affSColin Finck { 3625c2c66affSColin Finck return TRUE; 3626c2c66affSColin Finck } 3627c2c66affSColin Finck } 3628c2c66affSColin Finck } 3629c2c66affSColin Finck 3630c2c66affSColin Finck /* None of the callbacks handled the command */ 3631c2c66affSColin Finck return FALSE; 3632c2c66affSColin Finck } 3633c2c66affSColin Finck 3634c2c66affSColin Finck 3635c2c66affSColin Finck /*!\brief Parses command line and executes command if found 3636c2c66affSColin Finck * 3637c2c66affSColin Finck * \param Command Command line to parse and execute if possible. 3638c2c66affSColin Finck * 3639c2c66affSColin Finck * \retval TRUE Don't continue execution. 3640c2c66affSColin Finck * \retval FALSE Continue execution (leave KDB) 3641c2c66affSColin Finck */ 3642c2c66affSColin Finck static BOOLEAN 3643c2c66affSColin Finck KdbpDoCommand( 3644c2c66affSColin Finck IN PCHAR Command) 3645c2c66affSColin Finck { 3646c2c66affSColin Finck ULONG i; 3647c2c66affSColin Finck PCHAR p; 3648c2c66affSColin Finck ULONG Argc; 3649c2c66affSColin Finck // FIXME: for what do we need a 1024 characters command line and 256 tokens? 365040c57de7SHermès Bélusca-Maïto static PCHAR Argv[256]; 3651c2c66affSColin Finck static CHAR OrigCommand[1024]; 3652c2c66affSColin Finck 3653c2c66affSColin Finck RtlStringCbCopyA(OrigCommand, sizeof(OrigCommand), Command); 3654c2c66affSColin Finck 3655c2c66affSColin Finck Argc = 0; 3656c2c66affSColin Finck p = Command; 3657c2c66affSColin Finck 3658c2c66affSColin Finck for (;;) 3659c2c66affSColin Finck { 3660c2c66affSColin Finck while (*p == '\t' || *p == ' ') 3661c2c66affSColin Finck p++; 3662c2c66affSColin Finck 3663c2c66affSColin Finck if (*p == '\0') 3664c2c66affSColin Finck break; 3665c2c66affSColin Finck 3666c2c66affSColin Finck i = strcspn(p, "\t "); 3667c2c66affSColin Finck Argv[Argc++] = p; 3668c2c66affSColin Finck p += i; 3669c2c66affSColin Finck if (*p == '\0') 3670c2c66affSColin Finck break; 3671c2c66affSColin Finck 3672c2c66affSColin Finck *p = '\0'; 3673c2c66affSColin Finck p++; 3674c2c66affSColin Finck } 3675c2c66affSColin Finck 3676c2c66affSColin Finck if (Argc < 1) 3677c2c66affSColin Finck return TRUE; 3678c2c66affSColin Finck 3679c2c66affSColin Finck for (i = 0; i < RTL_NUMBER_OF(KdbDebuggerCommands); i++) 3680c2c66affSColin Finck { 3681c2c66affSColin Finck if (!KdbDebuggerCommands[i].Name) 3682c2c66affSColin Finck continue; 3683c2c66affSColin Finck 3684c2c66affSColin Finck if (strcmp(KdbDebuggerCommands[i].Name, Argv[0]) == 0) 3685c2c66affSColin Finck { 3686c2c66affSColin Finck return KdbDebuggerCommands[i].Fn(Argc, Argv); 3687c2c66affSColin Finck } 3688c2c66affSColin Finck } 3689c2c66affSColin Finck 3690c2c66affSColin Finck /* Now invoke the registered callbacks */ 3691c2c66affSColin Finck if (KdbpInvokeCliCallbacks(Command, Argc, Argv)) 3692c2c66affSColin Finck { 3693c2c66affSColin Finck return TRUE; 3694c2c66affSColin Finck } 3695c2c66affSColin Finck 3696c2c66affSColin Finck KdbpPrint("Command '%s' is unknown.\n", OrigCommand); 3697c2c66affSColin Finck return TRUE; 3698c2c66affSColin Finck } 3699c2c66affSColin Finck 3700c2c66affSColin Finck /*!\brief KDB Main Loop. 3701c2c66affSColin Finck * 3702c2c66affSColin Finck * \param EnteredOnSingleStep TRUE if KDB was entered on single step. 3703c2c66affSColin Finck */ 3704c2c66affSColin Finck VOID 3705c2c66affSColin Finck KdbpCliMainLoop( 3706c2c66affSColin Finck IN BOOLEAN EnteredOnSingleStep) 3707c2c66affSColin Finck { 3708c2c66affSColin Finck static CHAR Command[1024]; 3709c2c66affSColin Finck BOOLEAN Continue; 3710c2c66affSColin Finck 3711c2c66affSColin Finck if (EnteredOnSingleStep) 3712c2c66affSColin Finck { 37133726b992SJérôme Gardou if (!KdbSymPrintAddress((PVOID)KeGetContextPc(KdbCurrentTrapFrame), KdbCurrentTrapFrame)) 3714c2c66affSColin Finck { 37153726b992SJérôme Gardou KdbpPrint("<%p>", KeGetContextPc(KdbCurrentTrapFrame)); 3716c2c66affSColin Finck } 3717c2c66affSColin Finck 3718c2c66affSColin Finck KdbpPrint(": "); 37193726b992SJérôme Gardou if (KdbpDisassemble(KeGetContextPc(KdbCurrentTrapFrame), KdbUseIntelSyntax) < 0) 3720c2c66affSColin Finck { 3721c2c66affSColin Finck KdbpPrint("<INVALID>"); 3722c2c66affSColin Finck } 3723c2c66affSColin Finck KdbpPrint("\n"); 3724c2c66affSColin Finck } 3725c2c66affSColin Finck 3726c2c66affSColin Finck /* Flush the input buffer */ 3727c2c66affSColin Finck if (KdbDebugState & KD_DEBUG_KDSERIAL) 3728c2c66affSColin Finck { 3729c2c66affSColin Finck while (KdbpTryGetCharSerial(1) != -1); 3730c2c66affSColin Finck } 3731c2c66affSColin Finck else 3732c2c66affSColin Finck { 3733c2c66affSColin Finck ULONG ScanCode; 3734c2c66affSColin Finck while (KdbpTryGetCharKeyboard(&ScanCode, 1) != -1); 3735c2c66affSColin Finck } 3736c2c66affSColin Finck 3737c2c66affSColin Finck /* Main loop */ 3738c2c66affSColin Finck do 3739c2c66affSColin Finck { 3740c2c66affSColin Finck /* Reset the number of rows/cols printed */ 3741c2c66affSColin Finck KdbNumberOfRowsPrinted = KdbNumberOfColsPrinted = 0; 3742c2c66affSColin Finck 3743c2c66affSColin Finck /* Print the prompt */ 3744a890fc64SHermès Bélusca-Maïto KdbpPrint(KdbPromptString.Buffer); 3745c2c66affSColin Finck 3746c2c66affSColin Finck /* Read a command and remember it */ 3747c2c66affSColin Finck KdbpReadCommand(Command, sizeof(Command)); 3748c2c66affSColin Finck KdbpCommandHistoryAppend(Command); 3749c2c66affSColin Finck 3750c2c66affSColin Finck /* Reset the number of rows/cols printed and output aborted state */ 3751c2c66affSColin Finck KdbNumberOfRowsPrinted = KdbNumberOfColsPrinted = 0; 3752c2c66affSColin Finck KdbOutputAborted = FALSE; 3753c2c66affSColin Finck 3754c2c66affSColin Finck /* Call the command */ 3755c2c66affSColin Finck Continue = KdbpDoCommand(Command); 3756c2c66affSColin Finck KdbOutputAborted = FALSE; 3757c2c66affSColin Finck } 3758c2c66affSColin Finck while (Continue); 3759c2c66affSColin Finck } 3760c2c66affSColin Finck 3761c2c66affSColin Finck /*!\brief Called when a module is loaded. 3762c2c66affSColin Finck * 3763c2c66affSColin Finck * \param Name Filename of the module which was loaded. 3764c2c66affSColin Finck */ 3765c2c66affSColin Finck VOID 3766c2c66affSColin Finck KdbpCliModuleLoaded( 3767c2c66affSColin Finck IN PUNICODE_STRING Name) 3768c2c66affSColin Finck { 3769c2c66affSColin Finck if (!KdbBreakOnModuleLoad) 3770c2c66affSColin Finck return; 3771c2c66affSColin Finck 3772c2c66affSColin Finck KdbpPrint("Module %wZ loaded.\n", Name); 3773c2c66affSColin Finck DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); 3774c2c66affSColin Finck } 3775c2c66affSColin Finck 3776c2c66affSColin Finck /*!\brief This function is called by KdbEnterDebuggerException... 3777c2c66affSColin Finck * 3778c2c66affSColin Finck * Used to interpret the init file in a context with a trapframe setup 3779c2c66affSColin Finck * (KdbpCliInit call KdbEnter which will call KdbEnterDebuggerException which will 3780c2c66affSColin Finck * call this function if KdbInitFileBuffer is not NULL. 3781c2c66affSColin Finck */ 3782c2c66affSColin Finck VOID 3783c2c66affSColin Finck KdbpCliInterpretInitFile(VOID) 3784c2c66affSColin Finck { 3785c2c66affSColin Finck PCHAR p1, p2; 3786c2c66affSColin Finck INT i; 3787c2c66affSColin Finck CHAR c; 3788c2c66affSColin Finck 3789c2c66affSColin Finck /* Execute the commands in the init file */ 3790c2c66affSColin Finck DPRINT("KDB: Executing KDBinit file...\n"); 3791c2c66affSColin Finck p1 = KdbInitFileBuffer; 3792c2c66affSColin Finck while (p1[0] != '\0') 3793c2c66affSColin Finck { 3794c2c66affSColin Finck i = strcspn(p1, "\r\n"); 3795c2c66affSColin Finck if (i > 0) 3796c2c66affSColin Finck { 3797c2c66affSColin Finck c = p1[i]; 3798c2c66affSColin Finck p1[i] = '\0'; 3799c2c66affSColin Finck 3800c2c66affSColin Finck /* Look for "break" command and comments */ 3801c2c66affSColin Finck p2 = p1; 3802c2c66affSColin Finck 3803c2c66affSColin Finck while (isspace(p2[0])) 3804c2c66affSColin Finck p2++; 3805c2c66affSColin Finck 3806c2c66affSColin Finck if (strncmp(p2, "break", sizeof("break")-1) == 0 && 3807c2c66affSColin Finck (p2[sizeof("break")-1] == '\0' || isspace(p2[sizeof("break")-1]))) 3808c2c66affSColin Finck { 3809c2c66affSColin Finck /* break into the debugger */ 3810c2c66affSColin Finck KdbpCliMainLoop(FALSE); 3811c2c66affSColin Finck } 3812c2c66affSColin Finck else if (p2[0] != '#' && p2[0] != '\0') /* Ignore empty lines and comments */ 3813c2c66affSColin Finck { 3814c2c66affSColin Finck KdbpDoCommand(p1); 3815c2c66affSColin Finck } 3816c2c66affSColin Finck 3817c2c66affSColin Finck p1[i] = c; 3818c2c66affSColin Finck } 3819c2c66affSColin Finck 3820c2c66affSColin Finck p1 += i; 3821c2c66affSColin Finck while (p1[0] == '\r' || p1[0] == '\n') 3822c2c66affSColin Finck p1++; 3823c2c66affSColin Finck } 3824c2c66affSColin Finck DPRINT("KDB: KDBinit executed\n"); 3825c2c66affSColin Finck } 3826c2c66affSColin Finck 3827c2c66affSColin Finck /*!\brief Called when KDB is initialized 3828c2c66affSColin Finck * 3829c2c66affSColin Finck * Reads the KDBinit file from the SystemRoot\System32\drivers\etc directory and executes it. 3830c2c66affSColin Finck */ 3831c2c66affSColin Finck VOID 3832c2c66affSColin Finck KdbpCliInit(VOID) 3833c2c66affSColin Finck { 3834c2c66affSColin Finck NTSTATUS Status; 3835c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 3836c2c66affSColin Finck UNICODE_STRING FileName; 3837c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 3838c2c66affSColin Finck FILE_STANDARD_INFORMATION FileStdInfo; 3839c2c66affSColin Finck HANDLE hFile = NULL; 3840c2c66affSColin Finck INT FileSize; 3841c2c66affSColin Finck PCHAR FileBuffer; 3842c2c66affSColin Finck ULONG OldEflags; 3843c2c66affSColin Finck 3844c2c66affSColin Finck /* Initialize the object attributes */ 3845c2c66affSColin Finck RtlInitUnicodeString(&FileName, L"\\SystemRoot\\System32\\drivers\\etc\\KDBinit"); 3846b910409aSSerge Gautherie InitializeObjectAttributes(&ObjectAttributes, 3847b910409aSSerge Gautherie &FileName, 3848b910409aSSerge Gautherie OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 3849b910409aSSerge Gautherie NULL, 3850b910409aSSerge Gautherie NULL); 3851c2c66affSColin Finck 3852c2c66affSColin Finck /* Open the file */ 3853c2c66affSColin Finck Status = ZwOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE, 3854c2c66affSColin Finck &ObjectAttributes, &Iosb, 0, 3855c2c66affSColin Finck FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | 3856c2c66affSColin Finck FILE_NO_INTERMEDIATE_BUFFERING); 3857c2c66affSColin Finck if (!NT_SUCCESS(Status)) 3858c2c66affSColin Finck { 3859c2c66affSColin Finck DPRINT("Could not open \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%x)", Status); 3860c2c66affSColin Finck return; 3861c2c66affSColin Finck } 3862c2c66affSColin Finck 3863c2c66affSColin Finck /* Get the size of the file */ 3864c2c66affSColin Finck Status = ZwQueryInformationFile(hFile, &Iosb, &FileStdInfo, sizeof(FileStdInfo), 3865c2c66affSColin Finck FileStandardInformation); 3866c2c66affSColin Finck if (!NT_SUCCESS(Status)) 3867c2c66affSColin Finck { 3868c2c66affSColin Finck ZwClose(hFile); 3869c2c66affSColin Finck DPRINT("Could not query size of \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%x)", Status); 3870c2c66affSColin Finck return; 3871c2c66affSColin Finck } 3872c2c66affSColin Finck FileSize = FileStdInfo.EndOfFile.u.LowPart; 3873c2c66affSColin Finck 3874c2c66affSColin Finck /* Allocate memory for the file */ 3875c2c66affSColin Finck FileBuffer = ExAllocatePool(PagedPool, FileSize + 1); /* add 1 byte for terminating '\0' */ 3876c2c66affSColin Finck if (!FileBuffer) 3877c2c66affSColin Finck { 3878c2c66affSColin Finck ZwClose(hFile); 3879c2c66affSColin Finck DPRINT("Could not allocate %d bytes for KDBinit file\n", FileSize); 3880c2c66affSColin Finck return; 3881c2c66affSColin Finck } 3882c2c66affSColin Finck 3883c2c66affSColin Finck /* Load file into memory */ 388411baa0d7SSerge Gautherie Status = ZwReadFile(hFile, NULL, NULL, NULL, &Iosb, FileBuffer, FileSize, NULL, NULL); 3885c2c66affSColin Finck ZwClose(hFile); 3886c2c66affSColin Finck 3887c2c66affSColin Finck if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) 3888c2c66affSColin Finck { 3889c2c66affSColin Finck ExFreePool(FileBuffer); 3890c2c66affSColin Finck DPRINT("Could not read KDBinit file into memory (Status 0x%lx)\n", Status); 3891c2c66affSColin Finck return; 3892c2c66affSColin Finck } 3893c2c66affSColin Finck 3894c2c66affSColin Finck FileSize = min(FileSize, (INT)Iosb.Information); 3895c2c66affSColin Finck FileBuffer[FileSize] = '\0'; 3896c2c66affSColin Finck 3897c2c66affSColin Finck /* Enter critical section */ 3898c2c66affSColin Finck OldEflags = __readeflags(); 3899c2c66affSColin Finck _disable(); 3900c2c66affSColin Finck 3901c2c66affSColin Finck /* Interpret the init file... */ 3902c2c66affSColin Finck KdbInitFileBuffer = FileBuffer; 3903baa47fa5SHervé Poussineau //KdbEnter(); // FIXME 3904c2c66affSColin Finck KdbInitFileBuffer = NULL; 3905c2c66affSColin Finck 3906c2c66affSColin Finck /* Leave critical section */ 3907c2c66affSColin Finck __writeeflags(OldEflags); 3908c2c66affSColin Finck 3909c2c66affSColin Finck ExFreePool(FileBuffer); 3910c2c66affSColin Finck } 3911