2005-03-12 09:40:07 +00:00
/*
* ReactOS kernel
* Copyright ( C ) 2005 ReactOS Team
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
2009-10-27 10:34:16 +00:00
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2005-03-12 09:40:07 +00:00
*/
2006-09-24 10:39:43 +00:00
/*
2005-03-12 09:40:07 +00:00
* PROJECT : ReactOS kernel
2015-10-04 11:54:25 +00:00
* FILE : ntoskrnl / kdbg / kdb_cli . c
2005-03-12 09:40:07 +00:00
* PURPOSE : Kernel debugger command line interface
* PROGRAMMER : Gregor Anich ( blight @ blight . eu . org )
2020-01-26 17:59:05 +00:00
* Hervé Poussineau
2005-03-12 09:40:07 +00:00
* UPDATE HISTORY :
* Created 16 / 01 / 2005
*/
2005-05-09 01:38:29 +00:00
2005-03-12 09:40:07 +00:00
/* INCLUDES ******************************************************************/
# include <ntoskrnl.h>
2024-10-07 09:07:47 +00:00
2023-04-04 21:38:32 +00:00
# include "kdb.h"
2023-03-20 16:49:15 +00:00
# include "../kd/kdterminal.h"
2005-03-12 13:50:48 +00:00
2005-03-12 09:40:07 +00:00
# define NDEBUG
2023-04-12 16:38:47 +00:00
# include "debug.h"
2005-03-12 09:40:07 +00:00
/* DEFINES *******************************************************************/
# define KDB_ENTER_CONDITION_TO_STRING(cond) \
( ( cond ) = = KdbDoNotEnter ? " never " : \
( ( cond ) = = KdbEnterAlways ? " always " : \
( ( cond ) = = KdbEnterFromKmode ? " kmode " : " umode " ) ) )
# define KDB_ACCESS_TYPE_TO_STRING(type) \
( ( type ) = = KdbAccessRead ? " read " : \
( ( type ) = = KdbAccessWrite ? " write " : \
( ( type ) = = KdbAccessReadWrite ? " rdwr " : " exec " ) ) )
# define NPX_STATE_TO_STRING(state) \
2006-08-21 17:16:36 +00:00
( ( state ) = = NPX_STATE_LOADED ? " Loaded " : \
( ( state ) = = NPX_STATE_NOT_LOADED ? " Not loaded " : " Unknown " ) )
2005-03-12 09:40:07 +00:00
/* PROTOTYPES ****************************************************************/
2009-06-13 15:28:33 +00:00
static BOOLEAN KdbpCmdEvalExpression ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdDisassembleX ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdRegs ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdBackTrace ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdContinue ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdStep ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdBreakPointList ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdEnableDisableClearBreakPoint ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdBreakPoint ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdThread ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdProc ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdMod ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdGdtLdtIdt ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdPcr ( ULONG Argc , PCHAR Argv [ ] ) ;
2021-04-27 08:23:37 +00:00
# ifdef _M_IX86
2009-06-13 15:28:33 +00:00
static BOOLEAN KdbpCmdTss ( ULONG Argc , PCHAR Argv [ ] ) ;
2021-04-27 08:23:37 +00:00
# endif
2009-06-13 15:28:33 +00:00
static BOOLEAN KdbpCmdBugCheck ( ULONG Argc , PCHAR Argv [ ] ) ;
2015-09-12 20:10:43 +00:00
static BOOLEAN KdbpCmdReboot ( ULONG Argc , PCHAR Argv [ ] ) ;
2009-06-13 15:28:33 +00:00
static BOOLEAN KdbpCmdFilter ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdSet ( ULONG Argc , PCHAR Argv [ ] ) ;
static BOOLEAN KdbpCmdHelp ( ULONG Argc , PCHAR Argv [ ] ) ;
2011-07-07 19:18:16 +00:00
static BOOLEAN KdbpCmdDmesg ( ULONG Argc , PCHAR Argv [ ] ) ;
2005-03-12 09:40:07 +00:00
2013-03-13 18:13:55 +00:00
BOOLEAN ExpKdbgExtPool ( ULONG Argc , PCHAR Argv [ ] ) ;
2017-12-29 07:21:40 +00:00
BOOLEAN ExpKdbgExtPoolUsed ( ULONG Argc , PCHAR Argv [ ] ) ;
2019-01-06 10:54:05 +00:00
BOOLEAN ExpKdbgExtPoolFind ( ULONG Argc , PCHAR Argv [ ] ) ;
2018-01-24 20:45:37 +00:00
BOOLEAN ExpKdbgExtFileCache ( ULONG Argc , PCHAR Argv [ ] ) ;
2018-02-09 11:16:29 +00:00
BOOLEAN ExpKdbgExtDefWrites ( ULONG Argc , PCHAR Argv [ ] ) ;
2019-01-06 11:49:57 +00:00
BOOLEAN ExpKdbgExtIrpFind ( ULONG Argc , PCHAR Argv [ ] ) ;
2019-02-09 12:45:19 +00:00
BOOLEAN ExpKdbgExtHandle ( ULONG Argc , PCHAR Argv [ ] ) ;
2019-01-01 20:58:18 +00:00
2020-01-26 17:59:05 +00:00
extern char __ImageBase ;
2011-10-08 16:47:57 +00:00
# ifdef __ROS_DWARF__
2011-07-08 11:16:26 +00:00
static BOOLEAN KdbpCmdPrintStruct ( ULONG Argc , PCHAR Argv [ ] ) ;
# endif
2021-04-27 08:23:37 +00:00
/* Be more descriptive than intrinsics */
# ifndef Ke386GetGlobalDescriptorTable
# define Ke386GetGlobalDescriptorTable __sgdt
# endif
# ifndef Ke386GetLocalDescriptorTable
# define Ke386GetLocalDescriptorTable __sldt
# endif
/* Portability */
FORCEINLINE
ULONG_PTR
strtoulptr ( const char * nptr , char * * endptr , int base )
{
# ifdef _M_IX86
return strtoul ( nptr , endptr , base ) ;
# else
return strtoull ( nptr , endptr , base ) ;
# endif
}
2005-03-12 09:40:07 +00:00
/* GLOBALS *******************************************************************/
2020-03-31 21:40:14 +00:00
typedef
BOOLEAN
( NTAPI * PKDBG_CLI_ROUTINE ) (
IN PCHAR Command ,
IN ULONG Argc ,
IN PCH Argv [ ] ) ;
2012-10-01 23:06:32 +00:00
static PKDBG_CLI_ROUTINE KdbCliCallbacks [ 10 ] ;
2009-06-13 15:28:33 +00:00
static BOOLEAN KdbUseIntelSyntax = FALSE ; /* Set to TRUE for intel syntax */
static BOOLEAN KdbBreakOnModuleLoad = FALSE ; /* Set to TRUE to break into KDB when a module is loaded */
2005-03-12 09:40:07 +00:00
2009-06-13 15:28:33 +00:00
static ULONG KdbNumberOfRowsPrinted = 0 ;
static ULONG KdbNumberOfColsPrinted = 0 ;
static BOOLEAN KdbOutputAborted = FALSE ;
2011-11-21 05:28:08 +00:00
static BOOLEAN KdbRepeatLastCommand = FALSE ;
2005-03-12 09:40:07 +00:00
2022-11-28 02:13:31 +00:00
volatile PCHAR KdbInitFileBuffer = NULL ; /* Buffer where KDBinit file is loaded into during initialization */
2008-11-06 18:33:56 +00:00
BOOLEAN KdbpBugCheckRequested = FALSE ;
2005-03-12 09:40:07 +00:00
2022-07-10 13:01:01 +00:00
/* Variables for Dmesg */
static const ULONG KdpDmesgBufferSize = 128 * 1024 ; // 512*1024;
static PCHAR KdpDmesgBuffer = NULL ;
static volatile ULONG KdpDmesgCurrentPosition = 0 ;
static volatile ULONG KdpDmesgFreeBytes = 0 ;
static volatile ULONG KdbDmesgTotalWritten = 0 ;
static volatile BOOLEAN KdbpIsInDmesgMode = FALSE ;
static KSPIN_LOCK KdpDmesgLogSpinLock ;
2011-07-07 19:18:16 +00:00
2023-03-29 17:38:10 +00:00
const CSTRING KdbPromptStr = RTL_CONSTANT_STRING ( " kdb:> " ) ;
[NTOS:KD/KD64/KDBG] Share some code between our legacy KD/KDBG and KD64.
Our legacy KD module is slowly being phased out for the more recent KD64
Kernel Debugger that supports WinDbg, but at the same time we must retain
support for GCC debugging and the KDBG interface.
For the time being few #ifdef _WINKD_ have been introduced in KD64 so that
some of its code/data does not completely get shared yet with the legacy KD,
until the latter becomes phased out.
KD Modifications:
=================
- Remove the implementation of NtQueryDebugFilterState() /
NtSetDebugFilterState() that now comes entirely from KD64.
- Remove KD variables that are now shared with KD64.
- Share common code with KD64: KdpMoveMemory(), KdpZeroMemory(),
KdpCopyMemoryChunks(), KdpPrint(), KdpPrompt().
- KDBG: Remove the duplicated KdpCopyMemoryChunks() function.
- In KdpServiceDispatcher() and KdpEnterDebuggerException(), call the
KdpPrint() worker function that correctly probes and captures its arguments.
- Temporarily stub out KdEnterDebugger() and KdExitDebugger() that is used
by the shared code, until KD is removed and only the KD64 version of these
functions remain.
- Re-implement the KD/KDBG KdpPrompt() function using a custom KdpPromptString()
helper compatible with KD64, that is called by the KD64 implementation of
KdpPrompt(). This KdpPromptString() helper now issues the prompt on all
the KD loggers: e.g. if you use both at the same time COM-port and SCREEN
debugging, the prompt will appear on both. Before that the prompt was always
being displayed on COM port even if e.g. a SCREEN-only debug session was used...
- ppc_irq.c: Fix the prototype of KdpServiceDispatcher().
KD64 Fixes:
===========
- Initialize the MaximumLength member of the counted STRING variables
before using them elsewhere.
- Get rid of alloca() within SEH block in KdpPrint() (addendum to 7b95fcf9).
- Add the ROS-specific handy dump commands in KdSystemDebugControl().
2019-11-17 21:55:36 +00:00
2019-11-18 00:34:19 +00:00
//
// Debug Filter Component Table
//
2020-07-18 15:43:29 +00:00
# define KD_DEBUG_PRINT_FILTER(Name) \
{ # Name , DPFLTR_ # # Name # # _ID }
2019-11-18 00:34:19 +00:00
static struct
{
PCSTR Name ;
ULONG Id ;
}
ComponentTable [ ] =
{
//
// Default components
//
2020-07-18 15:43:29 +00:00
{ " WIN2000 " , MAXULONG } ,
KD_DEBUG_PRINT_FILTER ( DEFAULT ) ,
2019-11-18 00:34:19 +00:00
//
// Standard components
//
2020-07-18 15:43:29 +00:00
KD_DEBUG_PRINT_FILTER ( SYSTEM ) ,
KD_DEBUG_PRINT_FILTER ( SMSS ) ,
KD_DEBUG_PRINT_FILTER ( SETUP ) ,
KD_DEBUG_PRINT_FILTER ( NTFS ) ,
KD_DEBUG_PRINT_FILTER ( FSTUB ) ,
KD_DEBUG_PRINT_FILTER ( CRASHDUMP ) ,
KD_DEBUG_PRINT_FILTER ( CDAUDIO ) ,
KD_DEBUG_PRINT_FILTER ( CDROM ) ,
KD_DEBUG_PRINT_FILTER ( CLASSPNP ) ,
KD_DEBUG_PRINT_FILTER ( DISK ) ,
KD_DEBUG_PRINT_FILTER ( REDBOOK ) ,
KD_DEBUG_PRINT_FILTER ( STORPROP ) ,
KD_DEBUG_PRINT_FILTER ( SCSIPORT ) ,
KD_DEBUG_PRINT_FILTER ( SCSIMINIPORT ) ,
KD_DEBUG_PRINT_FILTER ( CONFIG ) ,
KD_DEBUG_PRINT_FILTER ( I8042PRT ) ,
KD_DEBUG_PRINT_FILTER ( SERMOUSE ) ,
KD_DEBUG_PRINT_FILTER ( LSERMOUS ) ,
KD_DEBUG_PRINT_FILTER ( KBDHID ) ,
KD_DEBUG_PRINT_FILTER ( MOUHID ) ,
KD_DEBUG_PRINT_FILTER ( KBDCLASS ) ,
KD_DEBUG_PRINT_FILTER ( MOUCLASS ) ,
KD_DEBUG_PRINT_FILTER ( TWOTRACK ) ,
KD_DEBUG_PRINT_FILTER ( WMILIB ) ,
KD_DEBUG_PRINT_FILTER ( ACPI ) ,
KD_DEBUG_PRINT_FILTER ( AMLI ) ,
KD_DEBUG_PRINT_FILTER ( HALIA64 ) ,
KD_DEBUG_PRINT_FILTER ( VIDEO ) ,
KD_DEBUG_PRINT_FILTER ( SVCHOST ) ,
KD_DEBUG_PRINT_FILTER ( VIDEOPRT ) ,
KD_DEBUG_PRINT_FILTER ( TCPIP ) ,
KD_DEBUG_PRINT_FILTER ( DMSYNTH ) ,
KD_DEBUG_PRINT_FILTER ( NTOSPNP ) ,
KD_DEBUG_PRINT_FILTER ( FASTFAT ) ,
KD_DEBUG_PRINT_FILTER ( SAMSS ) ,
KD_DEBUG_PRINT_FILTER ( PNPMGR ) ,
KD_DEBUG_PRINT_FILTER ( NETAPI ) ,
KD_DEBUG_PRINT_FILTER ( SCSERVER ) ,
KD_DEBUG_PRINT_FILTER ( SCCLIENT ) ,
KD_DEBUG_PRINT_FILTER ( SERIAL ) ,
KD_DEBUG_PRINT_FILTER ( SERENUM ) ,
KD_DEBUG_PRINT_FILTER ( UHCD ) ,
KD_DEBUG_PRINT_FILTER ( RPCPROXY ) ,
KD_DEBUG_PRINT_FILTER ( AUTOCHK ) ,
KD_DEBUG_PRINT_FILTER ( DCOMSS ) ,
KD_DEBUG_PRINT_FILTER ( UNIMODEM ) ,
KD_DEBUG_PRINT_FILTER ( SIS ) ,
KD_DEBUG_PRINT_FILTER ( FLTMGR ) ,
KD_DEBUG_PRINT_FILTER ( WMICORE ) ,
KD_DEBUG_PRINT_FILTER ( BURNENG ) ,
KD_DEBUG_PRINT_FILTER ( IMAPI ) ,
KD_DEBUG_PRINT_FILTER ( SXS ) ,
KD_DEBUG_PRINT_FILTER ( FUSION ) ,
KD_DEBUG_PRINT_FILTER ( IDLETASK ) ,
KD_DEBUG_PRINT_FILTER ( SOFTPCI ) ,
KD_DEBUG_PRINT_FILTER ( TAPE ) ,
KD_DEBUG_PRINT_FILTER ( MCHGR ) ,
KD_DEBUG_PRINT_FILTER ( IDEP ) ,
KD_DEBUG_PRINT_FILTER ( PCIIDE ) ,
KD_DEBUG_PRINT_FILTER ( FLOPPY ) ,
KD_DEBUG_PRINT_FILTER ( FDC ) ,
KD_DEBUG_PRINT_FILTER ( TERMSRV ) ,
KD_DEBUG_PRINT_FILTER ( W32TIME ) ,
KD_DEBUG_PRINT_FILTER ( PREFETCHER ) ,
KD_DEBUG_PRINT_FILTER ( RSFILTER ) ,
KD_DEBUG_PRINT_FILTER ( FCPORT ) ,
KD_DEBUG_PRINT_FILTER ( PCI ) ,
KD_DEBUG_PRINT_FILTER ( DMIO ) ,
KD_DEBUG_PRINT_FILTER ( DMCONFIG ) ,
KD_DEBUG_PRINT_FILTER ( DMADMIN ) ,
KD_DEBUG_PRINT_FILTER ( WSOCKTRANSPORT ) ,
KD_DEBUG_PRINT_FILTER ( VSS ) ,
KD_DEBUG_PRINT_FILTER ( PNPMEM ) ,
KD_DEBUG_PRINT_FILTER ( PROCESSOR ) ,
KD_DEBUG_PRINT_FILTER ( DMSERVER ) ,
KD_DEBUG_PRINT_FILTER ( SR ) ,
KD_DEBUG_PRINT_FILTER ( INFINIBAND ) ,
KD_DEBUG_PRINT_FILTER ( IHVDRIVER ) ,
KD_DEBUG_PRINT_FILTER ( IHVVIDEO ) ,
KD_DEBUG_PRINT_FILTER ( IHVAUDIO ) ,
KD_DEBUG_PRINT_FILTER ( IHVNETWORK ) ,
KD_DEBUG_PRINT_FILTER ( IHVSTREAMING ) ,
KD_DEBUG_PRINT_FILTER ( IHVBUS ) ,
KD_DEBUG_PRINT_FILTER ( HPS ) ,
KD_DEBUG_PRINT_FILTER ( RTLTHREADPOOL ) ,
KD_DEBUG_PRINT_FILTER ( LDR ) ,
KD_DEBUG_PRINT_FILTER ( TCPIP6 ) ,
KD_DEBUG_PRINT_FILTER ( ISAPNP ) ,
KD_DEBUG_PRINT_FILTER ( SHPC ) ,
KD_DEBUG_PRINT_FILTER ( STORPORT ) ,
KD_DEBUG_PRINT_FILTER ( STORMINIPORT ) ,
KD_DEBUG_PRINT_FILTER ( PRINTSPOOLER ) ,
KD_DEBUG_PRINT_FILTER ( VSSDYNDISK ) ,
KD_DEBUG_PRINT_FILTER ( VERIFIER ) ,
KD_DEBUG_PRINT_FILTER ( VDS ) ,
KD_DEBUG_PRINT_FILTER ( VDSBAS ) ,
KD_DEBUG_PRINT_FILTER ( VDSDYN ) , // Specified in Vista+
KD_DEBUG_PRINT_FILTER ( VDSDYNDR ) ,
KD_DEBUG_PRINT_FILTER ( VDSLDR ) , // Specified in Vista+
KD_DEBUG_PRINT_FILTER ( VDSUTIL ) ,
KD_DEBUG_PRINT_FILTER ( DFRGIFC ) ,
KD_DEBUG_PRINT_FILTER ( MM ) ,
KD_DEBUG_PRINT_FILTER ( DFSC ) ,
KD_DEBUG_PRINT_FILTER ( WOW64 ) ,
2019-11-18 00:34:19 +00:00
//
// Components specified in Vista+, some of which we also use in ReactOS
//
2020-07-18 15:43:29 +00:00
KD_DEBUG_PRINT_FILTER ( ALPC ) ,
KD_DEBUG_PRINT_FILTER ( WDI ) ,
KD_DEBUG_PRINT_FILTER ( PERFLIB ) ,
KD_DEBUG_PRINT_FILTER ( KTM ) ,
KD_DEBUG_PRINT_FILTER ( IOSTRESS ) ,
KD_DEBUG_PRINT_FILTER ( HEAP ) ,
KD_DEBUG_PRINT_FILTER ( WHEA ) ,
KD_DEBUG_PRINT_FILTER ( USERGDI ) ,
KD_DEBUG_PRINT_FILTER ( MMCSS ) ,
KD_DEBUG_PRINT_FILTER ( TPM ) ,
KD_DEBUG_PRINT_FILTER ( THREADORDER ) ,
KD_DEBUG_PRINT_FILTER ( ENVIRON ) ,
KD_DEBUG_PRINT_FILTER ( EMS ) ,
KD_DEBUG_PRINT_FILTER ( WDT ) ,
KD_DEBUG_PRINT_FILTER ( FVEVOL ) ,
KD_DEBUG_PRINT_FILTER ( NDIS ) ,
KD_DEBUG_PRINT_FILTER ( NVCTRACE ) ,
KD_DEBUG_PRINT_FILTER ( LUAFV ) ,
KD_DEBUG_PRINT_FILTER ( APPCOMPAT ) ,
KD_DEBUG_PRINT_FILTER ( USBSTOR ) ,
KD_DEBUG_PRINT_FILTER ( SBP2PORT ) ,
KD_DEBUG_PRINT_FILTER ( COVERAGE ) ,
KD_DEBUG_PRINT_FILTER ( CACHEMGR ) ,
KD_DEBUG_PRINT_FILTER ( MOUNTMGR ) ,
KD_DEBUG_PRINT_FILTER ( CFR ) ,
KD_DEBUG_PRINT_FILTER ( TXF ) ,
KD_DEBUG_PRINT_FILTER ( KSECDD ) ,
KD_DEBUG_PRINT_FILTER ( FLTREGRESS ) ,
KD_DEBUG_PRINT_FILTER ( MPIO ) ,
KD_DEBUG_PRINT_FILTER ( MSDSM ) ,
KD_DEBUG_PRINT_FILTER ( UDFS ) ,
KD_DEBUG_PRINT_FILTER ( PSHED ) ,
KD_DEBUG_PRINT_FILTER ( STORVSP ) ,
KD_DEBUG_PRINT_FILTER ( LSASS ) ,
KD_DEBUG_PRINT_FILTER ( SSPICLI ) ,
KD_DEBUG_PRINT_FILTER ( CNG ) ,
KD_DEBUG_PRINT_FILTER ( EXFAT ) ,
KD_DEBUG_PRINT_FILTER ( FILETRACE ) ,
KD_DEBUG_PRINT_FILTER ( XSAVE ) ,
KD_DEBUG_PRINT_FILTER ( SE ) ,
KD_DEBUG_PRINT_FILTER ( DRIVEEXTENDER ) ,
2020-07-18 14:25:45 +00:00
//
// Components specified in Windows 8
//
2020-07-18 15:43:29 +00:00
KD_DEBUG_PRINT_FILTER ( POWER ) ,
KD_DEBUG_PRINT_FILTER ( CRASHDUMPXHCI ) ,
KD_DEBUG_PRINT_FILTER ( GPIO ) ,
KD_DEBUG_PRINT_FILTER ( REFS ) ,
KD_DEBUG_PRINT_FILTER ( WER ) ,
2020-07-18 14:25:45 +00:00
//
// Components specified in Windows 10
//
2020-07-18 15:43:29 +00:00
KD_DEBUG_PRINT_FILTER ( CAPIMG ) ,
KD_DEBUG_PRINT_FILTER ( VPCI ) ,
KD_DEBUG_PRINT_FILTER ( STORAGECLASSMEMORY ) ,
KD_DEBUG_PRINT_FILTER ( FSLIB ) ,
2019-11-18 00:34:19 +00:00
} ;
2020-07-18 15:43:29 +00:00
# undef KD_DEBUG_PRINT_FILTER
2019-11-18 00:34:19 +00:00
//
// Command Table
//
2009-06-13 15:28:33 +00:00
static const struct
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
PCHAR Name ;
PCHAR Syntax ;
PCHAR Help ;
BOOLEAN ( * Fn ) ( ULONG Argc , PCHAR Argv [ ] ) ;
2005-03-12 09:40:07 +00:00
} KdbDebuggerCommands [ ] = {
2009-09-09 13:49:04 +00:00
/* Data */
{ NULL , NULL , " Data " , NULL } ,
{ " ? " , " ? expression " , " Evaluate expression. " , KdbpCmdEvalExpression } ,
2020-01-26 17:59:05 +00:00
# ifdef _M_IX86 // FIXME: this is broken on x64
2009-09-09 13:49:04 +00:00
{ " disasm " , " disasm [address] [L count] " , " Disassemble count instructions at address. " , KdbpCmdDisassembleX } ,
2020-01-26 17:59:05 +00:00
# endif // _M_IX86
2019-11-03 01:14:17 +00:00
{ " x " , " x [address] [L count] " , " Display count dwords, starting at address. " , KdbpCmdDisassembleX } ,
2009-09-09 13:49:04 +00:00
{ " regs " , " regs " , " Display general purpose registers. " , KdbpCmdRegs } ,
{ " sregs " , " sregs " , " Display status registers. " , KdbpCmdRegs } ,
{ " dregs " , " dregs " , " Display debug registers. " , KdbpCmdRegs } ,
2019-11-03 01:14:17 +00:00
{ " bt " , " bt [*frameaddr|thread id] " , " Prints current backtrace or from given frame address. " , KdbpCmdBackTrace } ,
2011-10-08 16:47:57 +00:00
# ifdef __ROS_DWARF__
2019-11-03 01:14:17 +00:00
{ " dt " , " dt [mod] [type] [addr] " , " Print a struct. The address is optional. " , KdbpCmdPrintStruct } ,
2011-07-08 11:16:26 +00:00
# endif
2009-09-09 13:49:04 +00:00
/* Flow control */
{ NULL , NULL , " Flow control " , NULL } ,
2019-11-03 01:14:17 +00:00
{ " cont " , " cont " , " Continue execution (leave debugger). " , KdbpCmdContinue } ,
2009-09-09 13:49:04 +00:00
{ " step " , " step [count] " , " Execute single instructions, stepping into interrupts. " , KdbpCmdStep } ,
{ " next " , " next [count] " , " Execute single instructions, skipping calls and reps. " , KdbpCmdStep } ,
{ " bl " , " bl " , " List breakpoints. " , KdbpCmdBreakPointList } ,
{ " be " , " be [breakpoint] " , " Enable breakpoint. " , KdbpCmdEnableDisableClearBreakPoint } ,
{ " bd " , " bd [breakpoint] " , " Disable breakpoint. " , KdbpCmdEnableDisableClearBreakPoint } ,
{ " bc " , " bc [breakpoint] " , " Clear breakpoint. " , KdbpCmdEnableDisableClearBreakPoint } ,
{ " bpx " , " bpx [address] [IF condition] " , " Set software execution breakpoint at address. " , KdbpCmdBreakPoint } ,
{ " bpm " , " bpm [r|w|rw|x] [byte|word|dword] [address] [IF condition] " , " Set memory breakpoint at address. " , KdbpCmdBreakPoint } ,
/* Process/Thread */
{ NULL , NULL , " Process/Thread " , NULL } ,
{ " thread " , " thread [list[ pid]|[attach ]tid] " , " List threads in current or specified process, display thread with given id or attach to thread. " , KdbpCmdThread } ,
{ " proc " , " proc [list|[attach ]pid] " , " List processes, display process with given id or attach to process. " , KdbpCmdProc } ,
/* System information */
{ NULL , NULL , " System info " , NULL } ,
{ " mod " , " mod [address] " , " List all modules or the one containing address. " , KdbpCmdMod } ,
2019-11-03 01:14:17 +00:00
{ " gdt " , " gdt " , " Display the global descriptor table. " , KdbpCmdGdtLdtIdt } ,
{ " ldt " , " ldt " , " Display the local descriptor table. " , KdbpCmdGdtLdtIdt } ,
{ " idt " , " idt " , " Display the interrupt descriptor table. " , KdbpCmdGdtLdtIdt } ,
{ " pcr " , " pcr " , " Display the processor control region. " , KdbpCmdPcr } ,
2021-04-27 08:23:37 +00:00
# ifdef _M_IX86
2019-11-03 02:44:55 +00:00
{ " tss " , " tss [selector|*descaddr] " , " Display the current task state segment, or the one specified by its selector number or descriptor address. " , KdbpCmdTss } ,
2021-04-27 08:23:37 +00:00
# endif
2009-09-09 13:49:04 +00:00
/* Others */
{ NULL , NULL , " Others " , NULL } ,
{ " bugcheck " , " bugcheck " , " Bugchecks the system. " , KdbpCmdBugCheck } ,
2015-09-12 20:10:43 +00:00
{ " reboot " , " reboot " , " Reboots the system. " , KdbpCmdReboot } ,
2019-11-03 01:14:17 +00:00
{ " filter " , " filter [error|warning|trace|info|level]+|-[componentname|default] " , " Enable/disable debug channels. " , KdbpCmdFilter } ,
2009-09-09 13:49:04 +00:00
{ " set " , " set [var] [value] " , " Sets var to value or displays value of var. " , KdbpCmdSet } ,
2011-07-07 19:18:16 +00:00
{ " dmesg " , " dmesg " , " Display debug messages on screen, with navigation on pages. " , KdbpCmdDmesg } ,
{ " kmsg " , " kmsg " , " Kernel dmesg. Alias for dmesg. " , KdbpCmdDmesg } ,
2013-03-13 18:13:55 +00:00
{ " help " , " help " , " Display help screen. " , KdbpCmdHelp } ,
2017-12-29 07:21:40 +00:00
{ " !pool " , " !pool [Address [Flags]] " , " Display information about pool allocations. " , ExpKdbgExtPool } ,
2017-12-29 19:28:54 +00:00
{ " !poolused " , " !poolused [Flags [Tag]] " , " Display pool usage. " , ExpKdbgExtPoolUsed } ,
2019-01-06 10:54:05 +00:00
{ " !poolfind " , " !poolfind Tag [Pool] " , " Search for pool tag allocations. " , ExpKdbgExtPoolFind } ,
2018-01-24 20:45:37 +00:00
{ " !filecache " , " !filecache " , " Display cache usage. " , ExpKdbgExtFileCache } ,
2018-02-09 11:16:29 +00:00
{ " !defwrites " , " !defwrites " , " Display cache write values. " , ExpKdbgExtDefWrites } ,
2019-11-03 01:14:17 +00:00
{ " !irpfind " , " !irpfind [Pool [startaddress [criteria data]]] " , " Lists IRPs potentially matching criteria. " , ExpKdbgExtIrpFind } ,
{ " !handle " , " !handle [Handle] " , " Displays info about handles. " , ExpKdbgExtHandle } ,
2005-03-12 09:40:07 +00:00
} ;
/* FUNCTIONS *****************************************************************/
/*!\brief Evaluates an expression...
*
* Much like KdbpRpnEvaluateExpression , but prints the error message ( if any )
* at the given offset .
*
* \ param Expression Expression to evaluate .
* \ param ErrOffset Offset ( in characters ) to print the error message at .
* \ param Result Receives the result on success .
*
* \ retval TRUE Success .
* \ retval FALSE Failure .
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2005-03-12 09:40:07 +00:00
KdbpEvaluateExpression (
2009-09-09 13:49:04 +00:00
IN PCHAR Expression ,
IN LONG ErrOffset ,
OUT PULONGLONG Result )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
static CHAR ErrMsgBuffer [ 130 ] = " ^ " ;
LONG ExpressionErrOffset = - 1 ;
PCHAR ErrMsg = ErrMsgBuffer ;
BOOLEAN Ok ;
Ok = KdbpRpnEvaluateExpression ( Expression , KdbCurrentTrapFrame , Result ,
& ExpressionErrOffset , ErrMsgBuffer + 2 ) ;
if ( ! Ok )
{
if ( ExpressionErrOffset > = 0 )
ExpressionErrOffset + = ErrOffset ;
else
ErrMsg + = 2 ;
KdbpPrint ( " %*s%s \n " , ExpressionErrOffset , " " , ErrMsg ) ;
}
return Ok ;
2005-03-12 09:40:07 +00:00
}
2013-03-13 18:13:55 +00:00
BOOLEAN
NTAPI
KdbpGetHexNumber (
IN PCHAR pszNum ,
OUT ULONG_PTR * pulValue )
{
char * endptr ;
/* Skip optional '0x' prefix */
if ( ( pszNum [ 0 ] = = ' 0 ' ) & & ( ( pszNum [ 1 ] = = ' x ' ) | | ( pszNum [ 1 ] = = ' X ' ) ) )
pszNum + = 2 ;
/* Make a number from the string (hex) */
* pulValue = strtoul ( pszNum , & endptr , 16 ) ;
return ( * endptr = = ' \0 ' ) ;
}
2005-03-12 09:40:07 +00:00
/*!\brief Evaluates an expression and displays the result.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdEvalExpression (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2020-01-26 17:59:05 +00:00
ULONG i ;
SIZE_T len ;
2009-09-09 13:49:04 +00:00
ULONGLONG Result = 0 ;
ULONG ul ;
LONG l = 0 ;
BOOLEAN Ok ;
if ( Argc < 2 )
{
KdbpPrint ( " ?: Argument required \n " ) ;
return TRUE ;
}
/* Put the arguments back together */
Argc - - ;
for ( i = 1 ; i < Argc ; i + + )
{
len = strlen ( Argv [ i ] ) ;
Argv [ i ] [ len ] = ' ' ;
}
/* Evaluate the expression */
2023-03-29 17:38:10 +00:00
Ok = KdbpEvaluateExpression ( Argv [ 1 ] , KdbPromptStr . Length + ( Argv [ 1 ] - Argv [ 0 ] ) , & Result ) ;
2009-09-09 13:49:04 +00:00
if ( Ok )
{
if ( Result > 0x00000000ffffffffLL )
{
if ( Result & 0x8000000000000000LL )
KdbpPrint ( " 0x%016I64x %20I64u %20I64d \n " , Result , Result , Result ) ;
else
KdbpPrint ( " 0x%016I64x %20I64u \n " , Result , Result ) ;
}
else
{
ul = ( ULONG ) Result ;
if ( ul < = 0xff & & ul > = 0x80 )
l = ( LONG ) ( ( CHAR ) ul ) ;
else if ( ul < = 0xffff & & ul > = 0x8000 )
l = ( LONG ) ( ( SHORT ) ul ) ;
else
l = ( LONG ) ul ;
if ( l < 0 )
KdbpPrint ( " 0x%08lx %10lu %10ld \n " , ul , ul , l ) ;
else
KdbpPrint ( " 0x%08lx %10lu \n " , ul , ul ) ;
}
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
2011-10-08 16:47:57 +00:00
# ifdef __ROS_DWARF__
2011-07-08 11:16:26 +00:00
/*!\brief Print a struct
*/
static VOID
KdbpPrintStructInternal
2011-08-10 16:12:45 +00:00
( PROSSYM_INFO Info ,
PCHAR Indent ,
BOOLEAN DoRead ,
PVOID BaseAddress ,
2011-07-08 11:16:26 +00:00
PROSSYM_AGGREGATE Aggregate )
{
ULONG i ;
ULONGLONG Result ;
PROSSYM_AGGREGATE_MEMBER Member ;
ULONG IndentLen = strlen ( Indent ) ;
2011-08-10 16:12:45 +00:00
ROSSYM_AGGREGATE MemberAggregate = { 0 } ;
2011-07-08 11:16:26 +00:00
for ( i = 0 ; i < Aggregate - > NumElements ; i + + ) {
Member = & Aggregate - > Elements [ i ] ;
KdbpPrint ( " %s%p+%x: %s " , Indent , ( ( PCHAR ) BaseAddress ) + Member - > BaseOffset , Member - > Size , Member - > Name ? Member - > Name : " <anoymous> " ) ;
if ( DoRead ) {
if ( ! strcmp ( Member - > Type , " _UNICODE_STRING " ) ) {
2022-07-17 17:17:18 +00:00
KdbpPrint ( " \" " ) ;
KdbpPrintUnicodeString ( ( ( PCHAR ) BaseAddress ) + Member - > BaseOffset ) ;
KdbpPrint ( " \" \n " ) ;
2011-07-08 11:16:26 +00:00
continue ;
} else if ( ! strcmp ( Member - > Type , " PUNICODE_STRING " ) ) {
2022-07-17 17:17:18 +00:00
KdbpPrint ( " \" " ) ;
KdbpPrintUnicodeString ( * ( ( ( PUNICODE_STRING * ) ( ( PCHAR ) BaseAddress ) + Member - > BaseOffset ) ) ) ;
KdbpPrint ( " \" \n " ) ;
2011-07-08 11:16:26 +00:00
continue ;
}
switch ( Member - > Size ) {
case 1 :
case 2 :
case 4 :
case 8 : {
Result = 0 ;
if ( NT_SUCCESS ( KdbpSafeReadMemory ( & Result , ( ( PCHAR ) BaseAddress ) + Member - > BaseOffset , Member - > Size ) ) ) {
if ( Member - > Bits ) {
Result > > = Member - > FirstBit ;
Result & = ( ( 1 < < Member - > Bits ) - 1 ) ;
}
KdbpPrint ( " %lx \n " , Result ) ;
}
else goto readfail ;
break ;
}
default : {
if ( Member - > Size < 8 ) {
if ( NT_SUCCESS ( KdbpSafeReadMemory ( & Result , ( ( PCHAR ) BaseAddress ) + Member - > BaseOffset , Member - > Size ) ) ) {
2011-08-10 16:12:45 +00:00
ULONG j ;
2011-07-08 11:16:26 +00:00
for ( j = 0 ; j < Member - > Size ; j + + ) {
KdbpPrint ( " %02x " , ( int ) ( Result & 0xff ) ) ;
Result > > = 8 ;
}
} else goto readfail ;
} else {
KdbpPrint ( " %s @ %p { \n " , Member - > Type , ( ( PCHAR ) BaseAddress ) + Member - > BaseOffset ) ;
Indent [ IndentLen ] = ' ' ;
if ( RosSymAggregate ( Info , Member - > Type , & MemberAggregate ) ) {
KdbpPrintStructInternal ( Info , Indent , DoRead , ( ( PCHAR ) BaseAddress ) + Member - > BaseOffset , & MemberAggregate ) ;
RosSymFreeAggregate ( & MemberAggregate ) ;
}
Indent [ IndentLen ] = 0 ;
KdbpPrint ( " %s} \n " , Indent ) ;
} break ;
}
}
} else {
readfail :
if ( Member - > Size < = 8 ) {
KdbpPrint ( " ?? \n " ) ;
} else {
KdbpPrint ( " %s @ %x { \n " , Member - > Type , Member - > BaseOffset ) ;
Indent [ IndentLen ] = ' ' ;
if ( RosSymAggregate ( Info , Member - > Type , & MemberAggregate ) ) {
KdbpPrintStructInternal ( Info , Indent , DoRead , BaseAddress , & MemberAggregate ) ;
RosSymFreeAggregate ( & MemberAggregate ) ;
}
Indent [ IndentLen ] = 0 ;
KdbpPrint ( " %s} \n " , Indent ) ;
}
}
}
}
PROSSYM_INFO KdbpSymFindCachedFile ( PUNICODE_STRING ModName ) ;
static BOOLEAN
KdbpCmdPrintStruct (
ULONG Argc ,
PCHAR Argv [ ] )
{
2011-08-10 16:12:45 +00:00
ULONG i ;
2011-07-08 11:16:26 +00:00
ULONGLONG Result = 0 ;
2024-10-07 09:07:47 +00:00
PVOID BaseAddress = NULL ;
2011-08-10 16:12:45 +00:00
ROSSYM_AGGREGATE Aggregate = { 0 } ;
UNICODE_STRING ModName = { 0 } ;
ANSI_STRING AnsiName = { 0 } ;
CHAR Indent [ 100 ] = { 0 } ;
PROSSYM_INFO Info ;
2011-07-08 11:16:26 +00:00
if ( Argc < 3 ) goto end ;
AnsiName . Length = AnsiName . MaximumLength = strlen ( Argv [ 1 ] ) ;
AnsiName . Buffer = Argv [ 1 ] ;
RtlAnsiStringToUnicodeString ( & ModName , & AnsiName , TRUE ) ;
2011-08-10 16:12:45 +00:00
Info = KdbpSymFindCachedFile ( & ModName ) ;
2011-07-08 11:16:26 +00:00
if ( ! Info | | ! RosSymAggregate ( Info , Argv [ 2 ] , & Aggregate ) ) {
DPRINT1 ( " Could not get aggregate \n " ) ;
goto end ;
}
2011-08-10 16:12:45 +00:00
2011-07-08 11:16:26 +00:00
// Get an argument for location if it was given
if ( Argc > 3 ) {
ULONG len ;
PCHAR ArgStart = Argv [ 3 ] ;
2024-10-07 09:07:47 +00:00
DPRINT ( " Trying to get expression \n " ) ;
2011-07-08 11:16:26 +00:00
for ( i = 3 ; i < Argc - 1 ; i + + )
{
len = strlen ( Argv [ i ] ) ;
Argv [ i ] [ len ] = ' ' ;
}
2011-08-10 16:12:45 +00:00
2011-07-08 11:16:26 +00:00
/* Evaluate the expression */
2024-10-07 09:07:47 +00:00
DPRINT ( " Arg: %s \n " , ArgStart ) ;
if ( KdbpEvaluateExpression ( ArgStart , strlen ( ArgStart ) , & Result ) )
2011-07-08 11:16:26 +00:00
BaseAddress = ( PVOID ) ( ULONG_PTR ) Result ;
}
2024-10-07 09:07:47 +00:00
DPRINT ( " BaseAddress: %p \n " , BaseAddress ) ;
2011-07-08 11:16:26 +00:00
KdbpPrintStructInternal ( Info , Indent , ! ! BaseAddress , BaseAddress , & Aggregate ) ;
end :
RosSymFreeAggregate ( & Aggregate ) ;
RtlFreeUnicodeString ( & ModName ) ;
return TRUE ;
}
2024-10-07 09:07:47 +00:00
# endif // __ROS_DWARF__
2011-07-08 11:16:26 +00:00
2019-11-18 00:34:19 +00:00
/*!\brief Retrieves the component ID corresponding to a given component name.
*
* \ param ComponentName The name of the component .
* \ param ComponentId Receives the component id on success .
*
* \ retval TRUE Success .
* \ retval FALSE Failure .
*/
static BOOLEAN
KdbpGetComponentId (
IN PCSTR ComponentName ,
OUT PULONG ComponentId )
{
ULONG i ;
2020-07-18 15:39:42 +00:00
for ( i = 0 ; i < RTL_NUMBER_OF ( ComponentTable ) ; i + + )
2019-11-18 00:34:19 +00:00
{
if ( _stricmp ( ComponentName , ComponentTable [ i ] . Name ) = = 0 )
{
* ComponentId = ComponentTable [ i ] . Id ;
return TRUE ;
}
}
return FALSE ;
}
/*!\brief Displays the list of active debug channels, or enable/disable debug channels.
2006-09-24 10:39:43 +00:00
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdFilter (
ULONG Argc ,
PCHAR Argv [ ] )
2006-09-24 10:39:43 +00:00
{
2008-05-15 20:43:26 +00:00
ULONG i , j , ComponentId , Level ;
ULONG set = DPFLTR_MASK , clear = DPFLTR_MASK ;
PCHAR pend ;
2019-11-18 00:34:19 +00:00
PCSTR opt , p ;
2009-09-09 13:49:04 +00:00
static struct
{
2019-11-18 00:34:19 +00:00
PCSTR Name ;
2008-05-15 20:43:26 +00:00
ULONG Level ;
2009-09-09 13:49:04 +00:00
}
debug_classes [ ] =
{
2019-11-18 00:34:19 +00:00
{ " error " , 1 < < DPFLTR_ERROR_LEVEL } ,
2008-05-15 20:43:26 +00:00
{ " warning " , 1 < < DPFLTR_WARNING_LEVEL } ,
2019-11-18 00:34:19 +00:00
{ " trace " , 1 < < DPFLTR_TRACE_LEVEL } ,
{ " info " , 1 < < DPFLTR_INFO_LEVEL } ,
2008-05-15 20:43:26 +00:00
} ;
2019-11-18 00:34:19 +00:00
if ( Argc < = 1 )
{
/* Display the list of available debug filter components */
KdbpPrint ( " REMARKS: \n "
" - The 'WIN2000' system-wide debug filter component is used for DbgPrint() \n "
" messages without Component ID and Level. \n "
" - The 'DEFAULT' debug filter component is used for DbgPrint() messages with \n "
" an unknown Component ID. \n \n " ) ;
KdbpPrint ( " The list of debug filter components currently available on your system is: \n \n " ) ;
2020-07-18 16:16:21 +00:00
KdbpPrint ( " Component Name Component ID \n "
" ================== ================ \n " ) ;
2020-07-18 15:39:42 +00:00
for ( i = 0 ; i < RTL_NUMBER_OF ( ComponentTable ) ; i + + )
2019-11-18 00:34:19 +00:00
{
2020-07-18 16:16:21 +00:00
KdbpPrint ( " %20s 0x%08lx \n " , ComponentTable [ i ] . Name , ComponentTable [ i ] . Id ) ;
2019-11-18 00:34:19 +00:00
}
return TRUE ;
}
2008-05-15 20:43:26 +00:00
for ( i = 1 ; i < Argc ; i + + )
{
opt = Argv [ i ] ;
p = opt + strcspn ( opt , " +- " ) ;
2019-11-18 00:34:19 +00:00
if ( ! p [ 0 ] ) p = opt ; /* Assume it's a debug channel name */
2008-05-15 20:43:26 +00:00
if ( p > opt )
{
2020-07-18 15:39:42 +00:00
for ( j = 0 ; j < RTL_NUMBER_OF ( debug_classes ) ; j + + )
2008-05-15 20:43:26 +00:00
{
SIZE_T len = strlen ( debug_classes [ j ] . Name ) ;
if ( len ! = ( p - opt ) )
continue ;
2019-11-18 00:34:19 +00:00
if ( _strnicmp ( opt , debug_classes [ j ] . Name , len ) = = 0 ) /* Found it */
2008-05-15 20:43:26 +00:00
{
if ( * p = = ' + ' )
set | = debug_classes [ j ] . Level ;
else
clear | = debug_classes [ j ] . Level ;
break ;
}
}
2020-07-18 15:39:42 +00:00
if ( j = = RTL_NUMBER_OF ( debug_classes ) )
2008-05-15 20:43:26 +00:00
{
Level = strtoul ( opt , & pend , 0 ) ;
if ( pend ! = p )
{
KdbpPrint ( " filter: bad class name '%.*s' \n " , p - opt , opt ) ;
continue ;
}
if ( * p = = ' + ' )
set | = Level ;
else
clear | = Level ;
}
}
else
{
if ( * p = = ' - ' )
2009-09-27 20:07:43 +00:00
clear = MAXULONG ;
2008-05-15 20:43:26 +00:00
else
2009-09-27 20:07:43 +00:00
set = MAXULONG ;
2008-05-15 20:43:26 +00:00
}
if ( * p = = ' + ' | | * p = = ' - ' )
p + + ;
if ( ! KdbpGetComponentId ( p , & ComponentId ) )
{
KdbpPrint ( " filter: '%s' is not a valid component name! \n " , p ) ;
return TRUE ;
}
/* Get current mask value */
NtSetDebugFilterState ( ComponentId , set , TRUE ) ;
NtSetDebugFilterState ( ComponentId , clear , FALSE ) ;
}
return TRUE ;
2006-09-24 10:39:43 +00:00
}
2005-03-12 09:40:07 +00:00
/*!\brief Disassembles 10 instructions at eip or given address or
* displays 16 dwords from memory at given address .
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdDisassembleX (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
ULONG Count ;
ULONG ul ;
INT i ;
ULONGLONG Result = 0 ;
2021-04-27 08:23:37 +00:00
ULONG_PTR Address = KeGetContextPc ( KdbCurrentTrapFrame ) ;
2009-09-09 13:49:04 +00:00
LONG InstLen ;
if ( Argv [ 0 ] [ 0 ] = = ' x ' ) /* display memory */
Count = 16 ;
else /* disassemble */
Count = 10 ;
if ( Argc > = 2 )
{
/* Check for [L count] part */
ul = 0 ;
if ( strcmp ( Argv [ Argc - 2 ] , " L " ) = = 0 )
{
ul = strtoul ( Argv [ Argc - 1 ] , NULL , 0 ) ;
if ( ul > 0 )
{
Count = ul ;
Argc - = 2 ;
}
}
else if ( Argv [ Argc - 1 ] [ 0 ] = = ' L ' )
{
ul = strtoul ( Argv [ Argc - 1 ] + 1 , NULL , 0 ) ;
if ( ul > 0 )
{
Count = ul ;
Argc - - ;
}
}
/* Put the remaining arguments back together */
Argc - - ;
for ( ul = 1 ; ul < Argc ; ul + + )
{
Argv [ ul ] [ strlen ( Argv [ ul ] ) ] = ' ' ;
}
Argc + + ;
}
/* Evaluate the expression */
if ( Argc > 1 )
{
2023-03-29 17:38:10 +00:00
if ( ! KdbpEvaluateExpression ( Argv [ 1 ] , KdbPromptStr . Length + ( Argv [ 1 ] - Argv [ 0 ] ) , & Result ) )
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
if ( Result > ( ULONGLONG ) ( ~ ( ( ULONG_PTR ) 0 ) ) )
2010-01-04 11:03:23 +00:00
KdbpPrint ( " Warning: Address %I64x is beeing truncated \n " , Result ) ;
2009-09-09 13:49:04 +00:00
Address = ( ULONG_PTR ) Result ;
}
else if ( Argv [ 0 ] [ 0 ] = = ' x ' )
{
KdbpPrint ( " x: Address argument required. \n " ) ;
return TRUE ;
}
if ( Argv [ 0 ] [ 0 ] = = ' x ' )
{
/* Display dwords */
ul = 0 ;
while ( Count > 0 )
{
2011-06-01 20:36:40 +00:00
if ( ! KdbSymPrintAddress ( ( PVOID ) Address , NULL ) )
2020-01-26 17:59:05 +00:00
KdbpPrint ( " <%p>: " , ( PVOID ) Address ) ;
2009-09-09 13:49:04 +00:00
else
KdbpPrint ( " : " ) ;
i = min ( 4 , Count ) ;
Count - = i ;
while ( - - i > = 0 )
{
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( & ul , ( PVOID ) Address , sizeof ( ul ) ) ) )
KdbpPrint ( " ???????? " ) ;
else
KdbpPrint ( " %08x " , ul ) ;
Address + = sizeof ( ul ) ;
}
KdbpPrint ( " \n " ) ;
}
}
else
{
/* Disassemble */
while ( Count - - > 0 )
{
2011-06-01 20:36:40 +00:00
if ( ! KdbSymPrintAddress ( ( PVOID ) Address , NULL ) )
2009-09-09 13:49:04 +00:00
KdbpPrint ( " <%08x>: " , Address ) ;
else
KdbpPrint ( " : " ) ;
InstLen = KdbpDisassemble ( Address , KdbUseIntelSyntax ) ;
if ( InstLen < 0 )
{
KdbpPrint ( " <INVALID> \n " ) ;
return TRUE ;
}
KdbpPrint ( " \n " ) ;
Address + = InstLen ;
}
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Displays CPU registers.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdRegs (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2020-04-08 21:08:57 +00:00
PCONTEXT Context = KdbCurrentTrapFrame ;
2009-09-09 13:49:04 +00:00
INT i ;
static const PCHAR EflagsBits [ 32 ] = { " CF " , NULL , " PF " , " BIT3 " , " AF " , " BIT5 " ,
" ZF " , " SF " , " TF " , " IF " , " DF " , " OF " ,
NULL , NULL , " NT " , " BIT15 " , " RF " , " VF " ,
" AC " , " VIF " , " VIP " , " ID " , " BIT22 " ,
" BIT23 " , " BIT24 " , " BIT25 " , " BIT26 " ,
" BIT27 " , " BIT28 " , " BIT29 " , " BIT30 " ,
" BIT31 " } ;
if ( Argv [ 0 ] [ 0 ] = = ' r ' ) /* regs */
{
2021-04-27 08:23:37 +00:00
# ifdef _M_IX86
2009-09-09 13:49:04 +00:00
KdbpPrint ( " CS:EIP 0x%04x:0x%08x \n "
" SS:ESP 0x%04x:0x%08x \n "
" EAX 0x%08x EBX 0x%08x \n "
" ECX 0x%08x EDX 0x%08x \n "
" ESI 0x%08x EDI 0x%08x \n "
" EBP 0x%08x \n " ,
2020-04-08 21:08:57 +00:00
Context - > SegCs & 0xFFFF , Context - > Eip ,
Context - > SegSs , Context - > Esp ,
Context - > Eax , Context - > Ebx ,
Context - > Ecx , Context - > Edx ,
Context - > Esi , Context - > Edi ,
Context - > Ebp ) ;
2021-04-27 08:23:37 +00:00
# else
KdbpPrint ( " CS:RIP 0x%04x:0x%p \n "
" SS:RSP 0x%04x:0x%p \n "
" RAX 0x%p RBX 0x%p \n "
" RCX 0x%p RDX 0x%p \n "
" RSI 0x%p RDI 0x%p \n "
" RBP 0x%p \n " ,
Context - > SegCs & 0xFFFF , Context - > Rip ,
Context - > SegSs , Context - > Rsp ,
Context - > Rax , Context - > Rbx ,
Context - > Rcx , Context - > Rdx ,
Context - > Rsi , Context - > Rdi ,
Context - > Rbp ) ;
# endif
2019-11-03 02:33:53 +00:00
/* Display the EFlags */
2020-04-08 21:08:57 +00:00
KdbpPrint ( " EFLAGS 0x%08x " , Context - > EFlags ) ;
2009-09-09 13:49:04 +00:00
for ( i = 0 ; i < 32 ; i + + )
{
if ( i = = 1 )
{
2020-04-08 21:08:57 +00:00
if ( ( Context - > EFlags & ( 1 < < 1 ) ) = = 0 )
2009-09-09 13:49:04 +00:00
KdbpPrint ( " !BIT1 " ) ;
}
else if ( i = = 12 )
{
2020-04-08 21:08:57 +00:00
KdbpPrint ( " IOPL%d " , ( Context - > EFlags > > 12 ) & 3 ) ;
2009-09-09 13:49:04 +00:00
}
else if ( i = = 13 )
{
}
2020-04-08 21:08:57 +00:00
else if ( ( Context - > EFlags & ( 1 < < i ) ) ! = 0 )
2009-09-09 13:49:04 +00:00
{
KdbpPrint ( EflagsBits [ i ] ) ;
}
}
KdbpPrint ( " \n " ) ;
}
else if ( Argv [ 0 ] [ 0 ] = = ' s ' ) /* sregs */
{
KdbpPrint ( " CS 0x%04x Index 0x%04x %cDT RPL%d \n " ,
2020-04-08 21:08:57 +00:00
Context - > SegCs & 0xffff , ( Context - > SegCs & 0xffff ) > > 3 ,
( Context - > SegCs & ( 1 < < 2 ) ) ? ' L ' : ' G ' , Context - > SegCs & 3 ) ;
2009-09-09 13:49:04 +00:00
KdbpPrint ( " DS 0x%04x Index 0x%04x %cDT RPL%d \n " ,
2020-04-08 21:08:57 +00:00
Context - > SegDs , Context - > SegDs > > 3 , ( Context - > SegDs & ( 1 < < 2 ) ) ? ' L ' : ' G ' , Context - > SegDs & 3 ) ;
2009-09-09 13:49:04 +00:00
KdbpPrint ( " ES 0x%04x Index 0x%04x %cDT RPL%d \n " ,
2020-04-08 21:08:57 +00:00
Context - > SegEs , Context - > SegEs > > 3 , ( Context - > SegEs & ( 1 < < 2 ) ) ? ' L ' : ' G ' , Context - > SegEs & 3 ) ;
2009-09-09 13:49:04 +00:00
KdbpPrint ( " FS 0x%04x Index 0x%04x %cDT RPL%d \n " ,
2020-04-08 21:08:57 +00:00
Context - > SegFs , Context - > SegFs > > 3 , ( Context - > SegFs & ( 1 < < 2 ) ) ? ' L ' : ' G ' , Context - > SegFs & 3 ) ;
2009-09-09 13:49:04 +00:00
KdbpPrint ( " GS 0x%04x Index 0x%04x %cDT RPL%d \n " ,
2020-04-08 21:08:57 +00:00
Context - > SegGs , Context - > SegGs > > 3 , ( Context - > SegGs & ( 1 < < 2 ) ) ? ' L ' : ' G ' , Context - > SegGs & 3 ) ;
2009-09-09 13:49:04 +00:00
KdbpPrint ( " SS 0x%04x Index 0x%04x %cDT RPL%d \n " ,
2020-04-08 21:08:57 +00:00
Context - > SegSs , Context - > SegSs > > 3 , ( Context - > SegSs & ( 1 < < 2 ) ) ? ' L ' : ' G ' , Context - > SegSs & 3 ) ;
2009-09-09 13:49:04 +00:00
}
else /* dregs */
{
ASSERT ( Argv [ 0 ] [ 0 ] = = ' d ' ) ;
KdbpPrint ( " DR0 0x%08x \n "
" DR1 0x%08x \n "
" DR2 0x%08x \n "
" DR3 0x%08x \n "
" DR6 0x%08x \n "
" DR7 0x%08x \n " ,
2020-04-08 21:08:57 +00:00
Context - > Dr0 , Context - > Dr1 , Context - > Dr2 , Context - > Dr3 ,
Context - > Dr6 , Context - > Dr7 ) ;
2009-09-09 13:49:04 +00:00
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
2021-04-27 08:23:37 +00:00
# ifdef _M_IX86
2019-11-03 02:44:55 +00:00
static PKTSS
KdbpRetrieveTss (
IN USHORT TssSelector ,
OUT PULONG pType OPTIONAL ,
IN PKDESCRIPTOR pGdtr OPTIONAL )
{
KDESCRIPTOR Gdtr ;
KGDTENTRY Desc ;
PKTSS Tss ;
/* Retrieve the Global Descriptor Table (user-provided or system) */
if ( pGdtr )
Gdtr = * pGdtr ;
else
Ke386GetGlobalDescriptorTable ( & Gdtr . Limit ) ;
/* Check limits */
if ( ( TssSelector & ( sizeof ( KGDTENTRY ) - 1 ) ) | |
( TssSelector < sizeof ( KGDTENTRY ) ) | |
( TssSelector + sizeof ( KGDTENTRY ) - 1 > Gdtr . Limit ) )
{
return NULL ;
}
/* Retrieve the descriptor */
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( & Desc ,
( PVOID ) ( Gdtr . Base + TssSelector ) ,
sizeof ( KGDTENTRY ) ) ) )
{
return NULL ;
}
/* Check for TSS32(Avl) or TSS32(Busy) */
if ( Desc . HighWord . Bits . Type ! = 9 & & Desc . HighWord . Bits . Type ! = 11 )
{
return NULL ;
}
if ( pType ) * pType = Desc . HighWord . Bits . Type ;
Tss = ( PKTSS ) ( ULONG_PTR ) ( Desc . BaseLow |
Desc . HighWord . Bytes . BaseMid < < 16 |
Desc . HighWord . Bytes . BaseHi < < 24 ) ;
return Tss ;
}
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
FORCEINLINE BOOLEAN
KdbpIsNestedTss (
IN USHORT TssSelector ,
IN PKTSS Tss )
2011-11-26 22:23:00 +00:00
{
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
USHORT Backlink ;
2011-11-26 22:23:00 +00:00
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
if ( ! Tss )
2011-11-26 22:23:00 +00:00
return FALSE ;
2020-01-26 17:59:05 +00:00
# ifdef _M_AMD64
// HACK
return FALSE ;
# else
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Retrieve the TSS Backlink */
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( & Backlink ,
( PVOID ) & Tss - > Backlink ,
sizeof ( USHORT ) ) ) )
{
2011-11-26 22:23:00 +00:00
return FALSE ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
}
2020-01-26 17:59:05 +00:00
# endif
2011-11-26 22:23:00 +00:00
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
return ( Backlink ! = 0 & & Backlink ! = TssSelector ) ;
}
2011-11-26 22:23:00 +00:00
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
static BOOLEAN
2020-04-08 21:08:57 +00:00
KdbpContextFromPrevTss (
IN OUT PCONTEXT Context ,
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
OUT PUSHORT TssSelector ,
IN OUT PKTSS * pTss ,
IN PKDESCRIPTOR pGdtr )
{
ULONG_PTR Eip , Ebp ;
USHORT Backlink ;
PKTSS Tss = * pTss ;
2011-11-26 22:23:00 +00:00
2020-01-26 17:59:05 +00:00
# ifdef _M_AMD64
// HACK
return FALSE ;
# else
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Retrieve the TSS Backlink */
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( & Backlink ,
2011-11-26 22:23:00 +00:00
( PVOID ) & Tss - > Backlink ,
sizeof ( USHORT ) ) ) )
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
{
2011-11-26 22:23:00 +00:00
return FALSE ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
}
2011-11-26 22:23:00 +00:00
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Retrieve the parent TSS */
Tss = KdbpRetrieveTss ( Backlink , NULL , pGdtr ) ;
if ( ! Tss )
2011-11-26 22:23:00 +00:00
return FALSE ;
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( & Eip ,
( PVOID ) & Tss - > Eip ,
sizeof ( ULONG_PTR ) ) ) )
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
{
2011-11-26 22:23:00 +00:00
return FALSE ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
}
2011-11-26 22:23:00 +00:00
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( & Ebp ,
( PVOID ) & Tss - > Ebp ,
sizeof ( ULONG_PTR ) ) ) )
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
{
2011-11-26 22:23:00 +00:00
return FALSE ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
}
2011-11-26 22:23:00 +00:00
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Return the parent TSS and its trap frame */
* TssSelector = Backlink ;
* pTss = Tss ;
2020-04-08 21:08:57 +00:00
Context - > Eip = Eip ;
Context - > Ebp = Ebp ;
2020-01-26 17:59:05 +00:00
# endif
2011-11-26 22:23:00 +00:00
return TRUE ;
}
2024-10-07 09:07:47 +00:00
# endif // _M_IX86
2011-11-26 22:23:00 +00:00
2020-01-26 17:59:05 +00:00
# ifdef _M_AMD64
static
BOOLEAN
GetNextFrame (
_Inout_ PCONTEXT Context )
{
PRUNTIME_FUNCTION FunctionEntry ;
ULONG64 ImageBase , EstablisherFrame ;
PVOID HandlerData ;
_SEH2_TRY
{
/* Lookup the FunctionEntry for the current RIP */
FunctionEntry = RtlLookupFunctionEntry ( Context - > Rip , & ImageBase , NULL ) ;
if ( FunctionEntry = = NULL )
{
/* No function entry, so this must be a leaf function. Pop the return address from the stack.
Note : this can happen after the first frame as the result of an exception */
Context - > Rip = * ( DWORD64 * ) Context - > Rsp ;
Context - > Rsp + = sizeof ( DWORD64 ) ;
return TRUE ;
}
else
{
RtlVirtualUnwind ( UNW_FLAG_NHANDLER ,
ImageBase ,
Context - > Rip ,
FunctionEntry ,
Context ,
& HandlerData ,
& EstablisherFrame ,
NULL ) ;
}
}
_SEH2_EXCEPT ( 1 )
{
return FALSE ;
}
_SEH2_END
return TRUE ;
}
static BOOLEAN
KdbpCmdBackTrace (
ULONG Argc ,
PCHAR Argv [ ] )
{
CONTEXT Context = * KdbCurrentTrapFrame ;
/* Walk through the frames */
KdbpPrint ( " Frames: \n " ) ;
2022-07-23 15:07:37 +00:00
do
2020-01-26 17:59:05 +00:00
{
2022-07-23 15:07:37 +00:00
BOOLEAN GotNextFrame ;
2020-01-26 17:59:05 +00:00
2022-07-23 15:07:37 +00:00
KdbpPrint ( " [%p] " , ( PVOID ) Context . Rsp ) ;
2020-01-26 17:59:05 +00:00
2022-07-23 15:07:37 +00:00
/* Print the location after the call instruction */
if ( ! KdbSymPrintAddress ( ( PVOID ) Context . Rip , & Context ) )
2020-01-26 17:59:05 +00:00
KdbpPrint ( " <%p> " , ( PVOID ) Context . Rip ) ;
2022-07-23 15:07:37 +00:00
KdbpPrint ( " \n " ) ;
2020-01-26 17:59:05 +00:00
if ( KdbOutputAborted )
break ;
2022-07-23 15:07:37 +00:00
GotNextFrame = GetNextFrame ( & Context ) ;
2020-01-26 17:59:05 +00:00
if ( ! GotNextFrame )
{
2022-07-23 15:07:37 +00:00
KdbpPrint ( " Couldn't get next frame \n " ) ;
2020-01-26 17:59:05 +00:00
break ;
}
2022-07-23 15:07:37 +00:00
} while ( ( Context . Rip ! = 0 ) & & ( Context . Rsp ! = 0 ) ) ;
2020-01-26 17:59:05 +00:00
return TRUE ;
}
# else
2005-03-12 09:40:07 +00:00
/*!\brief Displays a backtrace.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdBackTrace (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
ULONG ul ;
ULONGLONG Result = 0 ;
2020-04-08 21:08:57 +00:00
CONTEXT Context = * KdbCurrentTrapFrame ;
2021-04-27 08:23:37 +00:00
ULONG_PTR Frame = KeGetContextFrameRegister ( & Context ) ;
2009-09-09 13:49:04 +00:00
ULONG_PTR Address ;
if ( Argc > = 2 )
{
/* Check for [L count] part */
ul = 0 ;
if ( strcmp ( Argv [ Argc - 2 ] , " L " ) = = 0 )
{
ul = strtoul ( Argv [ Argc - 1 ] , NULL , 0 ) ;
if ( ul > 0 )
{
Argc - = 2 ;
}
}
else if ( Argv [ Argc - 1 ] [ 0 ] = = ' L ' )
{
ul = strtoul ( Argv [ Argc - 1 ] + 1 , NULL , 0 ) ;
if ( ul > 0 )
{
Argc - - ;
}
}
/* Put the remaining arguments back together */
Argc - - ;
for ( ul = 1 ; ul < Argc ; ul + + )
{
Argv [ ul ] [ strlen ( Argv [ ul ] ) ] = ' ' ;
}
Argc + + ;
}
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Check if a Frame Address or Thread ID is given */
2009-09-09 13:49:04 +00:00
if ( Argc > 1 )
{
if ( Argv [ 1 ] [ 0 ] = = ' * ' )
{
Argv [ 1 ] + + ;
/* Evaluate the expression */
2023-03-29 17:38:10 +00:00
if ( ! KdbpEvaluateExpression ( Argv [ 1 ] , KdbPromptStr . Length + ( Argv [ 1 ] - Argv [ 0 ] ) , & Result ) )
2009-09-09 13:49:04 +00:00
return TRUE ;
if ( Result > ( ULONGLONG ) ( ~ ( ( ULONG_PTR ) 0 ) ) )
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
KdbpPrint ( " Warning: Address %I64x is beeing truncated \n " , Result ) ;
2009-09-09 13:49:04 +00:00
Frame = ( ULONG_PTR ) Result ;
}
else
{
KdbpPrint ( " Thread backtrace not supported yet! \n " ) ;
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
}
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
2021-04-27 08:23:37 +00:00
# ifdef _M_IX86
KDESCRIPTOR Gdtr ;
USHORT TssSelector ;
PKTSS Tss ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Retrieve the Global Descriptor Table */
Ke386GetGlobalDescriptorTable ( & Gdtr . Limit ) ;
/* Retrieve the current (active) TSS */
TssSelector = Ke386GetTr ( ) ;
Tss = KdbpRetrieveTss ( TssSelector , NULL , & Gdtr ) ;
if ( KdbpIsNestedTss ( TssSelector , Tss ) )
2009-09-09 13:49:04 +00:00
{
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Display the active TSS if it is nested */
KdbpPrint ( " [Active TSS 0x%04x @ 0x%p] \n " , TssSelector , Tss ) ;
}
2021-04-27 08:23:37 +00:00
# endif
2009-09-09 13:49:04 +00:00
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* If no Frame Address or Thread ID was given, try printing the function at EIP */
if ( Argc < = 1 )
{
KdbpPrint ( " Eip: \n " ) ;
2021-04-27 08:23:37 +00:00
if ( ! KdbSymPrintAddress ( ( PVOID ) KeGetContextPc ( & Context ) , & Context ) )
KdbpPrint ( " <%p> \n " , KeGetContextPc ( & Context ) ) ;
2009-09-09 13:49:04 +00:00
else
KdbpPrint ( " \n " ) ;
}
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Walk through the frames */
2009-09-09 13:49:04 +00:00
KdbpPrint ( " Frames: \n " ) ;
for ( ; ; )
{
2011-06-01 20:36:40 +00:00
BOOLEAN GotNextFrame ;
2009-09-09 13:49:04 +00:00
if ( Frame = = 0 )
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
goto CheckForParentTSS ;
2009-09-09 13:49:04 +00:00
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
Address = 0 ;
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( & Address , ( PVOID ) ( Frame + sizeof ( ULONG_PTR ) ) , sizeof ( ULONG_PTR ) ) ) )
2009-09-09 13:49:04 +00:00
{
KdbpPrint ( " Couldn't access memory at 0x%p! \n " , Frame + sizeof ( ULONG_PTR ) ) ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
goto CheckForParentTSS ;
2009-09-09 13:49:04 +00:00
}
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
if ( Address = = 0 )
goto CheckForParentTSS ;
GotNextFrame = NT_SUCCESS ( KdbpSafeReadMemory ( & Frame , ( PVOID ) Frame , sizeof ( ULONG_PTR ) ) ) ;
if ( GotNextFrame )
2021-04-27 08:23:37 +00:00
{
KeSetContextFrameRegister ( & Context , Frame ) ;
}
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
// else
// Frame = 0;
2011-06-01 20:36:40 +00:00
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/* Print the location of the call instruction (assumed 5 bytes length) */
2020-04-08 21:08:57 +00:00
if ( ! KdbSymPrintAddress ( ( PVOID ) ( Address - 5 ) , & Context ) )
2009-09-09 13:49:04 +00:00
KdbpPrint ( " <%08x> \n " , Address ) ;
else
KdbpPrint ( " \n " ) ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
if ( KdbOutputAborted )
2009-09-09 13:49:04 +00:00
break ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
if ( ! GotNextFrame )
2011-11-26 22:23:00 +00:00
{
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
KdbpPrint ( " Couldn't access memory at 0x%p! \n " , Frame ) ;
goto CheckForParentTSS ; // break;
2011-11-26 22:23:00 +00:00
}
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
continue ;
CheckForParentTSS :
2021-04-27 08:23:37 +00:00
# ifndef _M_IX86
break ;
# else
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
/*
* We have ended the stack walking for the current ( active ) TSS .
* Check whether this TSS was nested , and if so switch to its parent
* and walk its stack .
*/
if ( ! KdbpIsNestedTss ( TssSelector , Tss ) )
break ; // The TSS is not nested, we stop there.
2020-04-08 21:08:57 +00:00
GotNextFrame = KdbpContextFromPrevTss ( & Context , & TssSelector , & Tss , & Gdtr ) ;
2011-06-01 20:36:40 +00:00
if ( ! GotNextFrame )
2009-09-09 13:49:04 +00:00
{
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
KdbpPrint ( " Couldn't access parent TSS 0x%04x \n " , Tss - > Backlink ) ;
break ; // Cannot retrieve the parent TSS, we stop there.
2009-09-09 13:49:04 +00:00
}
2021-04-27 08:23:37 +00:00
2020-04-08 21:08:57 +00:00
Address = Context . Eip ;
Frame = Context . Ebp ;
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
KdbpPrint ( " [Parent TSS 0x%04x @ 0x%p] \n " , TssSelector , Tss ) ;
2020-04-08 21:08:57 +00:00
if ( ! KdbSymPrintAddress ( ( PVOID ) Address , & Context ) )
[NTOS:KDBG] Rewrite the TSS handling code in the backtrace function, removing limitations (and bugs) of the original code.
CORE-16448, PR #2003. Supersedes PR #1997.
This commit supersedes commit 6c5c7809 (r54503).
The original code was checking for the NMI or Double-Fault TSS by
comparing the current stack-traced EIP address with their corresponding
trap handler address ranges. That method was actually buggy because
nothing was ensuring that the trap handlers were in the "expected" order
in the kernel binary (and in memory).
Instead, we now can handle completely generic nested TSSes, instead of
just the NMI or the Double-Fault ones.
The way we proceed is by performing the full stack backtrace of the
current TSS, then once finished we check whether this TSS is nested
(has a parent). If so we change the (cached) current TSS to the latter,
restarting the backtrace at the parent TSS' latest EIP.
Examples of stack backtraces:
=============================
- General Protection fault:
<snip>
*** Fatal System Error: 0x0000007f
(0x0000000D,0x00000000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:134826 (ntoskrnl/ke/i386/exp.c:1161 (KeRaiseUserException))>
<ntoskrnl.exe:19ae67 (ntoskrnl/ke/i386/traphdlr.c:1282 (KiTrap0DHandler))>
<ntoskrnl.exe:19a840 (:0 (KiTrap0D))>
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
- Double-fault (manually triggered by removing the GP handler):
Note how the backtrace explicitly specifies the crossed TSS boundaries,
and the trace in the parent TSS is indeed consistent with the previous
example. Note also that log2lines (used here to completely resolve the
trace) failed to see KiTrap08Handler(), which has been instead mistaken
for KiTrap09().
<snip>
*** Fatal System Error: 0x0000007f
(0x00000008,0x8009C000,0x00000000,0x00000000)
Entered debugger on embedded INT3 at 0x0008:0x80953528.
kdb:> bt
[Active TSS 0x0050 @ 0x80A10CA0]
Eip:
<ntoskrnl.exe:153529 (sdk/lib/rtl/i386/debug_asm.S:57 (RtlpBreakWithStatusInstruction))>
Frames:
<ntoskrnl.exe:899b0 (ntoskrnl/ke/bug.c:1136 (KeBugCheckWithTf))>
<ntoskrnl.exe:19a1d8 (ntoskrnl/ke/i386/traphdlr.c:917 (KiTrap09))> // <-- Here, log2lines fails to see it's actually KiTrap08Handler.
<ntoskrnl.exe:19a145 (:0 (KiTrap08))>
[Parent TSS 0x0028 @ 0x8009C000]
<ntoskrnl.exe:1925e6 (ntoskrnl/include/internal/i386/intrin_i.h:45 (KiInitMachineDependent))>
<ntoskrnl.exe:187688 (ntoskrnl/ke/krnlinit.c:305 (KeInitSystem))>
<ntoskrnl.exe:17fb2f (ntoskrnl/ex/init.c:1621 (Phase1InitializationDiscard))>
<ntoskrnl.exe:3247f (ntoskrnl/ex/init.c:2019 (Phase1Initialization))>
<ntoskrnl.exe:11c079 (ntoskrnl/ps/thread.c:156 (PspSystemThreadStartup))>
<ntoskrnl.exe:135c8a (ntoskrnl/ke/i386/thrdini.c:78 (KiThreadStartup))>
<ntoskrnl.exe:11c040 (ntoskrnl/ps/thread.c:141 (PspSystemThreadStartup))>
<5d8950ec>
Couldn't access memory at 0x83E58959!
</snip>
2019-10-28 00:01:23 +00:00
KdbpPrint ( " <%08x> \n " , Address ) ;
else
KdbpPrint ( " \n " ) ;
2021-04-27 08:23:37 +00:00
# endif
2009-09-09 13:49:04 +00:00
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
2020-01-26 17:59:05 +00:00
# endif // M_AMD64
2005-03-12 09:40:07 +00:00
/*!\brief Continues execution of the system/leaves KDB.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdContinue (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
/* Exit the main loop */
return FALSE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Continues execution of the system/leaves KDB.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdStep (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
ULONG Count = 1 ;
if ( Argc > 1 )
{
Count = strtoul ( Argv [ 1 ] , NULL , 0 ) ;
if ( Count = = 0 )
{
KdbpPrint ( " %s: Integer argument required \n " , Argv [ 0 ] ) ;
return TRUE ;
}
}
if ( Argv [ 0 ] [ 0 ] = = ' n ' )
KdbSingleStepOver = TRUE ;
else
KdbSingleStepOver = FALSE ;
/* Set the number of single steps and return to the interrupted code. */
KdbNumSingleSteps = Count ;
return FALSE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Lists breakpoints.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdBreakPointList (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
LONG l ;
ULONG_PTR Address = 0 ;
KDB_BREAKPOINT_TYPE Type = 0 ;
KDB_ACCESS_TYPE AccessType = 0 ;
UCHAR Size = 0 ;
UCHAR DebugReg = 0 ;
BOOLEAN Enabled = FALSE ;
BOOLEAN Global = FALSE ;
PEPROCESS Process = NULL ;
PCHAR str1 , str2 , ConditionExpr , GlobalOrLocal ;
CHAR Buffer [ 20 ] ;
l = KdbpGetNextBreakPointNr ( 0 ) ;
if ( l < 0 )
{
KdbpPrint ( " No breakpoints. \n " ) ;
return TRUE ;
}
KdbpPrint ( " Breakpoints: \n " ) ;
do
{
if ( ! KdbpGetBreakPointInfo ( l , & Address , & Type , & Size , & AccessType , & DebugReg ,
& Enabled , & Global , & Process , & ConditionExpr ) )
{
continue ;
}
if ( l = = KdbLastBreakPointNr )
{
str1 = " \x1b [1m* " ;
str2 = " \x1b [0m " ;
}
else
{
str1 = " " ;
str2 = " " ;
}
if ( Global )
{
GlobalOrLocal = " global " ;
}
else
{
GlobalOrLocal = Buffer ;
2020-01-26 17:59:05 +00:00
sprintf ( Buffer , " PID 0x%Ix " ,
2021-04-27 08:23:37 +00:00
( ULONG_PTR ) ( Process ? Process - > UniqueProcessId : INVALID_HANDLE_VALUE ) ) ;
2009-09-09 13:49:04 +00:00
}
if ( Type = = KdbBreakPointSoftware | | Type = = KdbBreakPointTemporary )
{
KdbpPrint ( " %s%03d BPX 0x%08x%s%s%s%s%s \n " ,
str1 , l , Address ,
Enabled ? " " : " disabled " ,
2005-03-12 09:40:07 +00:00
GlobalOrLocal ,
ConditionExpr ? " IF " : " " ,
ConditionExpr ? ConditionExpr : " " ,
str2 ) ;
2009-09-09 13:49:04 +00:00
}
else if ( Type = = KdbBreakPointHardware )
{
if ( ! Enabled )
{
KdbpPrint ( " %s%03d BPM 0x%08x %-5s %-5s disabled%s%s%s%s \n " , str1 , l , Address ,
KDB_ACCESS_TYPE_TO_STRING ( AccessType ) ,
Size = = 1 ? " byte " : ( Size = = 2 ? " word " : " dword " ) ,
GlobalOrLocal ,
ConditionExpr ? " IF " : " " ,
ConditionExpr ? ConditionExpr : " " ,
str2 ) ;
}
else
{
KdbpPrint ( " %s%03d BPM 0x%08x %-5s %-5s DR%d%s%s%s%s \n " , str1 , l , Address ,
KDB_ACCESS_TYPE_TO_STRING ( AccessType ) ,
Size = = 1 ? " byte " : ( Size = = 2 ? " word " : " dword " ) ,
DebugReg ,
GlobalOrLocal ,
ConditionExpr ? " IF " : " " ,
ConditionExpr ? ConditionExpr : " " ,
str2 ) ;
}
}
}
while ( ( l = KdbpGetNextBreakPointNr ( l + 1 ) ) > = 0 ) ;
2005-03-12 09:40:07 +00:00
2009-09-09 13:49:04 +00:00
return TRUE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Enables, disables or clears a breakpoint.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdEnableDisableClearBreakPoint (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
PCHAR pend ;
ULONG BreakPointNr ;
if ( Argc < 2 )
{
KdbpPrint ( " %s: argument required \n " , Argv [ 0 ] ) ;
return TRUE ;
}
pend = Argv [ 1 ] ;
BreakPointNr = strtoul ( Argv [ 1 ] , & pend , 0 ) ;
if ( pend = = Argv [ 1 ] | | * pend ! = ' \0 ' )
{
KdbpPrint ( " %s: integer argument required \n " , Argv [ 0 ] ) ;
return TRUE ;
}
if ( Argv [ 0 ] [ 1 ] = = ' e ' ) /* enable */
{
KdbpEnableBreakPoint ( BreakPointNr , NULL ) ;
}
else if ( Argv [ 0 ] [ 1 ] = = ' d ' ) /* disable */
{
KdbpDisableBreakPoint ( BreakPointNr , NULL ) ;
}
else /* clear */
{
ASSERT ( Argv [ 0 ] [ 1 ] = = ' c ' ) ;
KdbpDeleteBreakPoint ( BreakPointNr , NULL ) ;
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Sets a software or hardware (memory) breakpoint at the given address.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2005-03-12 09:40:07 +00:00
KdbpCmdBreakPoint ( ULONG Argc , PCHAR Argv [ ] )
{
2009-09-09 13:49:04 +00:00
ULONGLONG Result = 0 ;
ULONG_PTR Address ;
KDB_BREAKPOINT_TYPE Type ;
UCHAR Size = 0 ;
KDB_ACCESS_TYPE AccessType = 0 ;
ULONG AddressArgIndex , i ;
LONG ConditionArgIndex ;
BOOLEAN Global = TRUE ;
if ( Argv [ 0 ] [ 2 ] = = ' x ' ) /* software breakpoint */
{
if ( Argc < 2 )
{
KdbpPrint ( " bpx: Address argument required. \n " ) ;
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
2005-03-12 09:40:07 +00:00
2009-09-09 13:49:04 +00:00
AddressArgIndex = 1 ;
Type = KdbBreakPointSoftware ;
}
else /* memory breakpoint */
{
ASSERT ( Argv [ 0 ] [ 2 ] = = ' m ' ) ;
if ( Argc < 2 )
{
KdbpPrint ( " bpm: Access type argument required (one of r, w, rw, x) \n " ) ;
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
if ( _stricmp ( Argv [ 1 ] , " x " ) = = 0 )
AccessType = KdbAccessExec ;
else if ( _stricmp ( Argv [ 1 ] , " r " ) = = 0 )
AccessType = KdbAccessRead ;
else if ( _stricmp ( Argv [ 1 ] , " w " ) = = 0 )
AccessType = KdbAccessWrite ;
else if ( _stricmp ( Argv [ 1 ] , " rw " ) = = 0 )
AccessType = KdbAccessReadWrite ;
else
{
KdbpPrint ( " bpm: Unknown access type '%s' \n " , Argv [ 1 ] ) ;
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
2005-03-12 09:40:07 +00:00
2009-09-09 13:49:04 +00:00
if ( Argc < 3 )
{
KdbpPrint ( " bpm: %s argument required. \n " , AccessType = = KdbAccessExec ? " Address " : " Memory size " ) ;
return TRUE ;
}
AddressArgIndex = 3 ;
if ( _stricmp ( Argv [ 2 ] , " byte " ) = = 0 )
Size = 1 ;
else if ( _stricmp ( Argv [ 2 ] , " word " ) = = 0 )
Size = 2 ;
else if ( _stricmp ( Argv [ 2 ] , " dword " ) = = 0 )
Size = 4 ;
else if ( AccessType = = KdbAccessExec )
{
Size = 1 ;
AddressArgIndex - - ;
}
else
{
KdbpPrint ( " bpm: Unknown memory size '%s' \n " , Argv [ 2 ] ) ;
return TRUE ;
}
if ( Argc < = AddressArgIndex )
{
KdbpPrint ( " bpm: Address argument required. \n " ) ;
return TRUE ;
}
Type = KdbBreakPointHardware ;
}
/* Put the arguments back together */
ConditionArgIndex = - 1 ;
for ( i = AddressArgIndex ; i < ( Argc - 1 ) ; i + + )
{
if ( strcmp ( Argv [ i + 1 ] , " IF " ) = = 0 ) /* IF found */
{
ConditionArgIndex = i + 2 ;
2011-08-10 16:12:45 +00:00
if ( ( ULONG ) ConditionArgIndex > = Argc )
2009-09-09 13:49:04 +00:00
{
KdbpPrint ( " %s: IF requires condition expression. \n " , Argv [ 0 ] ) ;
return TRUE ;
}
for ( i = ConditionArgIndex ; i < ( Argc - 1 ) ; i + + )
Argv [ i ] [ strlen ( Argv [ i ] ) ] = ' ' ;
break ;
}
Argv [ i ] [ strlen ( Argv [ i ] ) ] = ' ' ;
}
/* Evaluate the address expression */
if ( ! KdbpEvaluateExpression ( Argv [ AddressArgIndex ] ,
2023-03-29 17:38:10 +00:00
KdbPromptStr . Length + ( Argv [ AddressArgIndex ] - Argv [ 0 ] ) ,
2009-09-09 13:49:04 +00:00
& Result ) )
{
return TRUE ;
}
if ( Result > ( ULONGLONG ) ( ~ ( ( ULONG_PTR ) 0 ) ) )
2010-01-04 11:03:23 +00:00
KdbpPrint ( " %s: Warning: Address %I64x is beeing truncated \n " , Argv [ 0 ] , Result ) ;
2009-09-09 13:49:04 +00:00
Address = ( ULONG_PTR ) Result ;
KdbpInsertBreakPoint ( Address , Type , Size , AccessType ,
( ConditionArgIndex < 0 ) ? NULL : Argv [ ConditionArgIndex ] ,
Global , NULL ) ;
return TRUE ;
}
/*!\brief Lists threads or switches to another thread context.
*/
static BOOLEAN
KdbpCmdThread (
ULONG Argc ,
PCHAR Argv [ ] )
{
PLIST_ENTRY Entry ;
PETHREAD Thread = NULL ;
PEPROCESS Process = NULL ;
BOOLEAN ReferencedThread = FALSE , ReferencedProcess = FALSE ;
2021-04-27 08:23:37 +00:00
PULONG_PTR Stack ;
PULONG_PTR Frame ;
ULONG_PTR Pc ;
ULONG_PTR ul = 0 ;
2009-09-09 13:49:04 +00:00
PCHAR State , pend , str1 , str2 ;
static const PCHAR ThreadStateToString [ DeferredReady + 1 ] =
{
" Initialized " , " Ready " , " Running " ,
" Standby " , " Terminated " , " Waiting " ,
" Transition " , " DeferredReady "
} ;
ASSERT ( KdbCurrentProcess ) ;
if ( Argc > = 2 & & _stricmp ( Argv [ 1 ] , " list " ) = = 0 )
{
Process = KdbCurrentProcess ;
if ( Argc > = 3 )
{
2021-04-27 08:23:37 +00:00
ul = strtoulptr ( Argv [ 2 ] , & pend , 0 ) ;
2009-09-09 13:49:04 +00:00
if ( Argv [ 2 ] = = pend )
{
KdbpPrint ( " thread: '%s' is not a valid process id! \n " , Argv [ 2 ] ) ;
return TRUE ;
}
if ( ! NT_SUCCESS ( PsLookupProcessByProcessId ( ( PVOID ) ul , & Process ) ) )
{
KdbpPrint ( " thread: Invalid process id! \n " ) ;
return TRUE ;
}
/* Remember our reference */
ReferencedProcess = TRUE ;
}
Entry = Process - > ThreadListHead . Flink ;
if ( Entry = = & Process - > ThreadListHead )
{
if ( Argc > = 3 )
2021-04-27 08:23:37 +00:00
KdbpPrint ( " No threads in process 0x%px! \n " , ( PVOID ) ul ) ;
2005-06-18 11:42:42 +00:00
else
2009-09-09 13:49:04 +00:00
KdbpPrint ( " No threads in current process! \n " ) ;
if ( ReferencedProcess )
ObDereferenceObject ( Process ) ;
2005-05-09 01:38:29 +00:00
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
KdbpPrint ( " TID State Prior. Affinity EBP EIP \n " ) ;
do
{
Thread = CONTAINING_RECORD ( Entry , ETHREAD , ThreadListEntry ) ;
if ( Thread = = KdbCurrentThread )
{
str1 = " \x1b [1m* " ;
str2 = " \x1b [0m " ;
}
else
{
str1 = " " ;
str2 = " " ;
}
2010-05-04 23:17:30 +00:00
if ( ! Thread - > Tcb . InitialStack )
{
/* Thread has no kernel stack (probably terminated) */
2021-04-27 08:23:37 +00:00
Stack = Frame = NULL ;
Pc = 0 ;
2010-05-04 23:17:30 +00:00
}
else if ( Thread - > Tcb . TrapFrame )
2009-09-09 13:49:04 +00:00
{
2021-04-27 08:23:37 +00:00
Stack = ( PULONG_PTR ) KeGetTrapFrameStackRegister ( Thread - > Tcb . TrapFrame ) ;
Frame = ( PULONG_PTR ) KeGetTrapFrameFrameRegister ( Thread - > Tcb . TrapFrame ) ;
Pc = KeGetTrapFramePc ( Thread - > Tcb . TrapFrame ) ;
2009-09-09 13:49:04 +00:00
}
else
{
2021-04-27 08:23:37 +00:00
Stack = ( PULONG_PTR ) Thread - > Tcb . KernelStack ;
Frame = ( PULONG_PTR ) Stack [ 4 ] ;
Pc = 0 ;
2009-09-09 13:49:04 +00:00
2021-04-27 08:23:37 +00:00
if ( Frame ) /* FIXME: Should we attach to the process to read Ebp[1]? */
KdbpSafeReadMemory ( & Pc , Frame + 1 , sizeof ( Pc ) ) ;
2009-09-09 13:49:04 +00:00
}
if ( Thread - > Tcb . State < ( DeferredReady + 1 ) )
State = ThreadStateToString [ Thread - > Tcb . State ] ;
else
State = " Unknown " ;
KdbpPrint ( " %s0x%08x %-11s %3d 0x%08x 0x%08x 0x%08x%s \n " ,
str1 ,
Thread - > Cid . UniqueThread ,
State ,
Thread - > Tcb . Priority ,
Thread - > Tcb . Affinity ,
2021-04-27 08:23:37 +00:00
Frame ,
Pc ,
2009-09-09 13:49:04 +00:00
str2 ) ;
Entry = Entry - > Flink ;
}
while ( Entry ! = & Process - > ThreadListHead ) ;
/* Release our reference, if any */
if ( ReferencedProcess )
ObDereferenceObject ( Process ) ;
}
else if ( Argc > = 2 & & _stricmp ( Argv [ 1 ] , " attach " ) = = 0 )
{
if ( Argc < 3 )
{
KdbpPrint ( " thread attach: thread id argument required! \n " ) ;
return TRUE ;
}
2021-04-27 08:23:37 +00:00
ul = strtoulptr ( Argv [ 2 ] , & pend , 0 ) ;
2009-09-09 13:49:04 +00:00
if ( Argv [ 2 ] = = pend )
{
KdbpPrint ( " thread attach: '%s' is not a valid thread id! \n " , Argv [ 2 ] ) ;
return TRUE ;
}
if ( ! KdbpAttachToThread ( ( PVOID ) ul ) )
{
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
KdbpPrint ( " Attached to thread 0x%08x. \n " , ul ) ;
}
else
{
Thread = KdbCurrentThread ;
if ( Argc > = 2 )
{
2021-04-27 08:23:37 +00:00
ul = strtoulptr ( Argv [ 1 ] , & pend , 0 ) ;
2009-09-09 13:49:04 +00:00
if ( Argv [ 1 ] = = pend )
{
KdbpPrint ( " thread: '%s' is not a valid thread id! \n " , Argv [ 1 ] ) ;
return TRUE ;
}
if ( ! NT_SUCCESS ( PsLookupThreadByThreadId ( ( PVOID ) ul , & Thread ) ) )
{
KdbpPrint ( " thread: Invalid thread id! \n " ) ;
return TRUE ;
}
/* Remember our reference */
ReferencedThread = TRUE ;
}
if ( Thread - > Tcb . State < ( DeferredReady + 1 ) )
State = ThreadStateToString [ Thread - > Tcb . State ] ;
else
State = " Unknown " ;
KdbpPrint ( " %s "
" TID: 0x%08x \n "
" State: %s (0x%x) \n "
" Priority: %d \n "
" Affinity: 0x%08x \n "
" Initial Stack: 0x%08x \n "
" Stack Limit: 0x%08x \n "
" Stack Base: 0x%08x \n "
" Kernel Stack: 0x%08x \n "
" Trap Frame: 0x%08x \n "
2021-04-28 13:58:01 +00:00
# ifndef _M_AMD64
" NPX State: %s (0x%x) \n "
# endif
, ( Argc < 2 ) ? " Current Thread: \n " : " "
, Thread - > Cid . UniqueThread
, State , Thread - > Tcb . State
, Thread - > Tcb . Priority
, Thread - > Tcb . Affinity
, Thread - > Tcb . InitialStack
, Thread - > Tcb . StackLimit
, Thread - > Tcb . StackBase
, Thread - > Tcb . KernelStack
, Thread - > Tcb . TrapFrame
2021-04-27 08:23:37 +00:00
# ifndef _M_AMD64
, NPX_STATE_TO_STRING ( Thread - > Tcb . NpxState ) , Thread - > Tcb . NpxState
# endif
2021-04-28 13:58:01 +00:00
) ;
2009-09-09 13:49:04 +00:00
/* Release our reference if we had one */
if ( ReferencedThread )
ObDereferenceObject ( Thread ) ;
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Lists processes or switches to another process context.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdProc (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
PLIST_ENTRY Entry ;
PEPROCESS Process ;
BOOLEAN ReferencedProcess = FALSE ;
PCHAR State , pend , str1 , str2 ;
2021-04-27 08:23:37 +00:00
ULONG_PTR ul ;
2009-09-09 13:49:04 +00:00
extern LIST_ENTRY PsActiveProcessHead ;
if ( Argc > = 2 & & _stricmp ( Argv [ 1 ] , " list " ) = = 0 )
{
Entry = PsActiveProcessHead . Flink ;
if ( ! Entry | | Entry = = & PsActiveProcessHead )
{
KdbpPrint ( " No processes in the system! \n " ) ;
return TRUE ;
}
KdbpPrint ( " PID State Filename \n " ) ;
do
{
Process = CONTAINING_RECORD ( Entry , EPROCESS , ActiveProcessLinks ) ;
if ( Process = = KdbCurrentProcess )
{
str1 = " \x1b [1m* " ;
str2 = " \x1b [0m " ;
}
else
{
str1 = " " ;
str2 = " " ;
}
State = ( ( Process - > Pcb . State = = ProcessInMemory ) ? " In Memory " :
( ( Process - > Pcb . State = = ProcessOutOfMemory ) ? " Out of Memory " : " In Transition " ) ) ;
KdbpPrint ( " %s0x%08x %-10s %s%s \n " ,
str1 ,
Process - > UniqueProcessId ,
State ,
Process - > ImageFileName ,
str2 ) ;
Entry = Entry - > Flink ;
}
while ( Entry ! = & PsActiveProcessHead ) ;
}
else if ( Argc > = 2 & & _stricmp ( Argv [ 1 ] , " attach " ) = = 0 )
{
if ( Argc < 3 )
{
KdbpPrint ( " process attach: process id argument required! \n " ) ;
return TRUE ;
}
2021-04-27 08:23:37 +00:00
ul = strtoulptr ( Argv [ 2 ] , & pend , 0 ) ;
2009-09-09 13:49:04 +00:00
if ( Argv [ 2 ] = = pend )
{
KdbpPrint ( " process attach: '%s' is not a valid process id! \n " , Argv [ 2 ] ) ;
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
if ( ! KdbpAttachToProcess ( ( PVOID ) ul ) )
{
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
2021-04-27 08:23:37 +00:00
KdbpPrint ( " Attached to process 0x%p, thread 0x%p. \n " , ( PVOID ) ul ,
KdbCurrentThread - > Cid . UniqueThread ) ;
2009-09-09 13:49:04 +00:00
}
else
{
Process = KdbCurrentProcess ;
if ( Argc > = 2 )
{
2021-04-27 08:23:37 +00:00
ul = strtoulptr ( Argv [ 1 ] , & pend , 0 ) ;
2009-09-09 13:49:04 +00:00
if ( Argv [ 1 ] = = pend )
{
KdbpPrint ( " proc: '%s' is not a valid process id! \n " , Argv [ 1 ] ) ;
return TRUE ;
}
if ( ! NT_SUCCESS ( PsLookupProcessByProcessId ( ( PVOID ) ul , & Process ) ) )
{
KdbpPrint ( " proc: Invalid process id! \n " ) ;
return TRUE ;
}
/* Remember our reference */
ReferencedProcess = TRUE ;
}
State = ( ( Process - > Pcb . State = = ProcessInMemory ) ? " In Memory " :
( ( Process - > Pcb . State = = ProcessOutOfMemory ) ? " Out of Memory " : " In Transition " ) ) ;
KdbpPrint ( " %s "
" PID: 0x%08x \n "
" State: %s (0x%x) \n "
" Image Filename: %s \n " ,
( Argc < 2 ) ? " Current process: \n " : " " ,
Process - > UniqueProcessId ,
State , Process - > Pcb . State ,
Process - > ImageFileName ) ;
2009-01-14 00:34:24 +00:00
/* Release our reference, if any */
2009-09-09 13:49:04 +00:00
if ( ReferencedProcess )
ObDereferenceObject ( Process ) ;
}
2005-03-12 09:40:07 +00:00
2009-09-09 13:49:04 +00:00
return TRUE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Lists loaded modules or the one containing the specified address.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdMod (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
ULONGLONG Result = 0 ;
ULONG_PTR Address ;
2009-09-22 21:31:55 +00:00
PLDR_DATA_TABLE_ENTRY LdrEntry ;
2009-09-09 13:49:04 +00:00
BOOLEAN DisplayOnlyOneModule = FALSE ;
INT i = 0 ;
if ( Argc > = 2 )
{
/* Put the arguments back together */
Argc - - ;
while ( - - Argc > = 1 )
Argv [ Argc ] [ strlen ( Argv [ Argc ] ) ] = ' ' ;
/* Evaluate the expression */
2023-03-29 17:38:10 +00:00
if ( ! KdbpEvaluateExpression ( Argv [ 1 ] , KdbPromptStr . Length + ( Argv [ 1 ] - Argv [ 0 ] ) , & Result ) )
2009-09-09 13:49:04 +00:00
{
return TRUE ;
}
if ( Result > ( ULONGLONG ) ( ~ ( ( ULONG_PTR ) 0 ) ) )
2010-01-04 11:03:23 +00:00
KdbpPrint ( " %s: Warning: Address %I64x is beeing truncated \n " , Argv [ 0 ] , Result ) ;
2009-09-09 13:49:04 +00:00
Address = ( ULONG_PTR ) Result ;
2021-06-22 17:46:27 +00:00
if ( ! KdbpSymFindModule ( ( PVOID ) Address , - 1 , & LdrEntry ) )
2009-09-09 13:49:04 +00:00
{
KdbpPrint ( " No module containing address 0x%p found! \n " , Address ) ;
return TRUE ;
}
DisplayOnlyOneModule = TRUE ;
}
else
{
2021-06-22 17:46:27 +00:00
if ( ! KdbpSymFindModule ( NULL , 0 , & LdrEntry ) )
2009-09-09 13:49:04 +00:00
{
2020-01-26 17:59:05 +00:00
ULONG_PTR ntoskrnlBase = ( ULONG_PTR ) __ImageBase ;
2009-09-09 13:49:04 +00:00
KdbpPrint ( " Base Size Name \n " ) ;
2020-01-26 17:59:05 +00:00
KdbpPrint ( " %p %08x %s \n " , ( PVOID ) ntoskrnlBase , 0 , " ntoskrnl.exe " ) ;
2009-09-09 13:49:04 +00:00
return TRUE ;
}
i = 1 ;
}
KdbpPrint ( " Base Size Name \n " ) ;
for ( ; ; )
{
2022-07-17 17:17:18 +00:00
KdbpPrint ( " %p %08x " , LdrEntry - > DllBase , LdrEntry - > SizeOfImage ) ;
KdbpPrintUnicodeString ( & LdrEntry - > BaseDllName ) ;
KdbpPrint ( " \n " ) ;
2009-09-09 13:49:04 +00:00
2021-06-22 17:46:27 +00:00
if ( DisplayOnlyOneModule | | ! KdbpSymFindModule ( NULL , i + + , & LdrEntry ) )
2009-09-09 13:49:04 +00:00
break ;
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
2019-11-03 01:14:17 +00:00
/*!\brief Displays GDT, LDT or IDT.
2005-03-12 09:40:07 +00:00
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdGdtLdtIdt (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-21 15:20:18 +00:00
KDESCRIPTOR Reg ;
2009-09-09 13:49:04 +00:00
ULONG SegDesc [ 2 ] ;
ULONG SegBase ;
ULONG SegLimit ;
PCHAR SegType ;
USHORT SegSel ;
UCHAR Type , Dpl ;
INT i ;
ULONG ul ;
if ( Argv [ 0 ] [ 0 ] = = ' i ' )
{
/* Read IDTR */
2009-09-21 15:20:18 +00:00
__sidt ( & Reg . Limit ) ;
2009-09-09 13:49:04 +00:00
if ( Reg . Limit < 7 )
{
KdbpPrint ( " Interrupt descriptor table is empty. \n " ) ;
2005-03-12 09:40:07 +00:00
return TRUE ;
2009-09-09 13:49:04 +00:00
}
KdbpPrint ( " IDT Base: 0x%08x Limit: 0x%04x \n " , Reg . Base , Reg . Limit ) ;
KdbpPrint ( " Idx Type Seg. Sel. Offset DPL \n " ) ;
for ( i = 0 ; ( i + sizeof ( SegDesc ) - 1 ) < = Reg . Limit ; i + = 8 )
{
2021-04-27 08:23:37 +00:00
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( SegDesc , ( PVOID ) ( ( ULONG_PTR ) Reg . Base + i ) , sizeof ( SegDesc ) ) ) )
2005-03-12 09:40:07 +00:00
{
2021-04-27 08:23:37 +00:00
KdbpPrint ( " Couldn't access memory at 0x%p! \n " , ( PVOID ) ( ( ULONG_PTR ) Reg . Base + i ) ) ;
2009-09-09 13:49:04 +00:00
return TRUE ;
2005-03-12 09:40:07 +00:00
}
2009-09-09 13:49:04 +00:00
Dpl = ( ( SegDesc [ 1 ] > > 13 ) & 3 ) ;
if ( ( SegDesc [ 1 ] & 0x1f00 ) = = 0x0500 ) /* Task gate */
SegType = " TASKGATE " ;
else if ( ( SegDesc [ 1 ] & 0x1fe0 ) = = 0x0e00 ) /* 32 bit Interrupt gate */
SegType = " INTGATE32 " ;
else if ( ( SegDesc [ 1 ] & 0x1fe0 ) = = 0x0600 ) /* 16 bit Interrupt gate */
SegType = " INTGATE16 " ;
else if ( ( SegDesc [ 1 ] & 0x1fe0 ) = = 0x0f00 ) /* 32 bit Trap gate */
SegType = " TRAPGATE32 " ;
else if ( ( SegDesc [ 1 ] & 0x1fe0 ) = = 0x0700 ) /* 16 bit Trap gate */
SegType = " TRAPGATE16 " ;
else
SegType = " UNKNOWN " ;
if ( ( SegDesc [ 1 ] & ( 1 < < 15 ) ) = = 0 ) /* not present */
{
KdbpPrint ( " %03d %-10s [NP] [NP] %02d \n " ,
i / 8 , SegType , Dpl ) ;
}
else if ( ( SegDesc [ 1 ] & 0x1f00 ) = = 0x0500 ) /* Task gate */
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
SegSel = SegDesc [ 0 ] > > 16 ;
KdbpPrint ( " %03d %-10s 0x%04x %02d \n " ,
i / 8 , SegType , SegSel , Dpl ) ;
2005-03-12 09:40:07 +00:00
}
else
2009-09-09 13:49:04 +00:00
{
SegSel = SegDesc [ 0 ] > > 16 ;
SegBase = ( SegDesc [ 1 ] & 0xffff0000 ) | ( SegDesc [ 0 ] & 0x0000ffff ) ;
KdbpPrint ( " %03d %-10s 0x%04x 0x%08x %02d \n " ,
i / 8 , SegType , SegSel , SegBase , Dpl ) ;
}
}
}
else
{
ul = 0 ;
if ( Argv [ 0 ] [ 0 ] = = ' g ' )
{
/* Read GDTR */
2009-09-21 15:20:18 +00:00
Ke386GetGlobalDescriptorTable ( & Reg . Limit ) ;
2009-09-09 13:49:04 +00:00
i = 8 ;
}
else
{
ASSERT ( Argv [ 0 ] [ 0 ] = = ' l ' ) ;
/* Read LDTR */
2021-04-27 08:23:37 +00:00
Ke386GetLocalDescriptorTable ( & Reg . Limit ) ;
2009-09-27 10:09:38 +00:00
Reg . Base = 0 ;
2009-09-09 13:49:04 +00:00
i = 0 ;
ul = 1 < < 2 ;
}
if ( Reg . Limit < 7 )
{
KdbpPrint ( " %s descriptor table is empty. \n " ,
Argv [ 0 ] [ 0 ] = = ' g ' ? " Global " : " Local " ) ;
return TRUE ;
}
KdbpPrint ( " %cDT Base: 0x%08x Limit: 0x%04x \n " ,
Argv [ 0 ] [ 0 ] = = ' g ' ? ' G ' : ' L ' , Reg . Base , Reg . Limit ) ;
KdbpPrint ( " Idx Sel. Type Base Limit DPL Attribs \n " ) ;
for ( ; ( i + sizeof ( SegDesc ) - 1 ) < = Reg . Limit ; i + = 8 )
{
2021-04-27 08:23:37 +00:00
if ( ! NT_SUCCESS ( KdbpSafeReadMemory ( SegDesc , ( PVOID ) ( ( ULONG_PTR ) Reg . Base + i ) , sizeof ( SegDesc ) ) ) )
2009-09-09 13:49:04 +00:00
{
2021-04-27 08:23:37 +00:00
KdbpPrint ( " Couldn't access memory at 0x%p! \n " , ( ULONG_PTR ) Reg . Base + i ) ;
2009-09-09 13:49:04 +00:00
return TRUE ;
}
Dpl = ( ( SegDesc [ 1 ] > > 13 ) & 3 ) ;
Type = ( ( SegDesc [ 1 ] > > 8 ) & 0xf ) ;
SegBase = SegDesc [ 0 ] > > 16 ;
SegBase | = ( SegDesc [ 1 ] & 0xff ) < < 16 ;
SegBase | = SegDesc [ 1 ] & 0xff000000 ;
SegLimit = SegDesc [ 0 ] & 0x0000ffff ;
SegLimit | = ( SegDesc [ 1 ] > > 16 ) & 0xf ;
2005-03-12 09:40:07 +00:00
2009-09-09 13:49:04 +00:00
if ( ( SegDesc [ 1 ] & ( 1 < < 23 ) ) ! = 0 )
{
SegLimit * = 4096 ;
SegLimit + = 4095 ;
}
2005-03-12 09:40:07 +00:00
else
2009-09-09 13:49:04 +00:00
{
SegLimit + + ;
}
2005-03-12 09:40:07 +00:00
if ( ( SegDesc [ 1 ] & ( 1 < < 12 ) ) = = 0 ) /* System segment */
{
2009-09-09 13:49:04 +00:00
switch ( Type )
{
2019-10-27 23:59:44 +00:00
case 1 : SegType = " TSS16(Avl) " ; break ;
case 2 : SegType = " LDT " ; break ;
case 3 : SegType = " TSS16(Busy) " ; break ;
case 4 : SegType = " CALLGATE16 " ; break ;
case 5 : SegType = " TASKGATE " ; break ;
case 6 : SegType = " INTGATE16 " ; break ;
case 7 : SegType = " TRAPGATE16 " ; break ;
case 9 : SegType = " TSS32(Avl) " ; break ;
case 11 : SegType = " TSS32(Busy) " ; break ;
case 12 : SegType = " CALLGATE32 " ; break ;
case 14 : SegType = " INTGATE32 " ; break ;
case 15 : SegType = " TRAPGATE32 " ; break ;
default : SegType = " UNKNOWN " ; break ;
2009-09-09 13:49:04 +00:00
}
if ( ! ( Type > = 1 & & Type < = 3 ) & &
Type ! = 9 & & Type ! = 11 )
{
SegBase = 0 ;
SegLimit = 0 ;
}
2005-03-12 09:40:07 +00:00
}
else if ( ( SegDesc [ 1 ] & ( 1 < < 11 ) ) = = 0 ) /* Data segment */
{
2009-09-09 13:49:04 +00:00
if ( ( SegDesc [ 1 ] & ( 1 < < 22 ) ) ! = 0 )
SegType = " DATA32 " ;
else
SegType = " DATA16 " ;
2005-03-12 09:40:07 +00:00
}
else /* Code segment */
{
2009-09-09 13:49:04 +00:00
if ( ( SegDesc [ 1 ] & ( 1 < < 22 ) ) ! = 0 )
SegType = " CODE32 " ;
else
SegType = " CODE16 " ;
2005-03-12 09:40:07 +00:00
}
2005-05-09 01:38:29 +00:00
2019-10-27 23:59:44 +00:00
if ( ( SegDesc [ 1 ] & ( 1 < < 15 ) ) = = 0 ) /* Not present */
2009-09-09 13:49:04 +00:00
{
KdbpPrint ( " %03d 0x%04x %-11s [NP] [NP] %02d NP \n " ,
i / 8 , i | Dpl | ul , SegType , Dpl ) ;
}
else
{
KdbpPrint ( " %03d 0x%04x %-11s 0x%08x 0x%08x %02d " ,
i / 8 , i | Dpl | ul , SegType , SegBase , SegLimit , Dpl ) ;
if ( ( SegDesc [ 1 ] & ( 1 < < 12 ) ) = = 0 ) /* System segment */
{
/* FIXME: Display system segment */
}
else if ( ( SegDesc [ 1 ] & ( 1 < < 11 ) ) = = 0 ) /* Data segment */
{
if ( ( SegDesc [ 1 ] & ( 1 < < 10 ) ) ! = 0 ) /* Expand-down */
KdbpPrint ( " E " ) ;
KdbpPrint ( ( SegDesc [ 1 ] & ( 1 < < 9 ) ) ? " R/W " : " R " ) ;
if ( ( SegDesc [ 1 ] & ( 1 < < 8 ) ) ! = 0 )
KdbpPrint ( " A " ) ;
}
else /* Code segment */
{
if ( ( SegDesc [ 1 ] & ( 1 < < 10 ) ) ! = 0 ) /* Conforming */
KdbpPrint ( " C " ) ;
KdbpPrint ( ( SegDesc [ 1 ] & ( 1 < < 9 ) ) ? " R/X " : " X " ) ;
if ( ( SegDesc [ 1 ] & ( 1 < < 8 ) ) ! = 0 )
KdbpPrint ( " A " ) ;
}
if ( ( SegDesc [ 1 ] & ( 1 < < 20 ) ) ! = 0 )
KdbpPrint ( " AVL " ) ;
KdbpPrint ( " \n " ) ;
}
}
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Displays the KPCR
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdPcr (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
PKIPCR Pcr = ( PKIPCR ) KeGetPcr ( ) ;
2019-11-03 01:17:15 +00:00
KdbpPrint ( " Current PCR is at 0x%p. \n " , Pcr ) ;
2020-01-26 17:59:05 +00:00
# ifdef _M_IX86
2009-09-09 13:49:04 +00:00
KdbpPrint ( " Tib.ExceptionList: 0x%08x \n "
" Tib.StackBase: 0x%08x \n "
" Tib.StackLimit: 0x%08x \n "
" Tib.SubSystemTib: 0x%08x \n "
" Tib.FiberData/Version: 0x%08x \n "
" Tib.ArbitraryUserPointer: 0x%08x \n "
" Tib.Self: 0x%08x \n "
2017-12-12 11:50:58 +00:00
" SelfPcr: 0x%08x \n "
2009-09-09 13:49:04 +00:00
" PCRCB: 0x%08x \n "
" Irql: 0x%02x \n "
" IRR: 0x%08x \n "
" IrrActive: 0x%08x \n "
" IDR: 0x%08x \n "
" KdVersionBlock: 0x%08x \n "
" IDT: 0x%08x \n "
" GDT: 0x%08x \n "
" TSS: 0x%08x \n "
" MajorVersion: 0x%04x \n "
" MinorVersion: 0x%04x \n "
" SetMember: 0x%08x \n "
" StallScaleFactor: 0x%08x \n "
" Number: 0x%02x \n "
" L2CacheAssociativity: 0x%02x \n "
" VdmAlert: 0x%08x \n "
" L2CacheSize: 0x%08x \n "
2021-04-27 08:23:37 +00:00
" InterruptMode: 0x%08x \n "
, Pcr - > NtTib . ExceptionList , Pcr - > NtTib . StackBase , Pcr - > NtTib . StackLimit ,
2009-09-09 13:49:04 +00:00
Pcr - > NtTib . SubSystemTib , Pcr - > NtTib . FiberData , Pcr - > NtTib . ArbitraryUserPointer ,
2021-04-27 08:23:37 +00:00
Pcr - > NtTib . Self
, Pcr - > SelfPcr
, Pcr - > Prcb , Pcr - > Irql
, Pcr - > IRR , Pcr - > IrrActive , Pcr - > IDR
, Pcr - > KdVersionBlock
, Pcr - > IDT , Pcr - > GDT , Pcr - > TSS
, Pcr - > MajorVersion , Pcr - > MinorVersion
, Pcr - > SetMember
, Pcr - > StallScaleFactor
, Pcr - > Number
, Pcr - > SecondLevelCacheAssociativity
, Pcr - > VdmAlert
, Pcr - > SecondLevelCacheSize
2020-01-26 17:59:05 +00:00
, Pcr - > InterruptMode ) ;
# else
KdbpPrint ( " GdtBase: 0x%p \n " , Pcr - > GdtBase ) ;
KdbpPrint ( " TssBase: 0x%p \n " , Pcr - > TssBase ) ;
KdbpPrint ( " UserRsp: 0x%p \n " , ( PVOID ) Pcr - > UserRsp ) ;
KdbpPrint ( " Self: 0x%p \n " , Pcr - > Self ) ;
KdbpPrint ( " CurrentPrcb: 0x%p \n " , Pcr - > CurrentPrcb ) ;
KdbpPrint ( " LockArray: 0x%p \n " , Pcr - > LockArray ) ;
KdbpPrint ( " Used_Self: 0x%p \n " , Pcr - > Used_Self ) ;
KdbpPrint ( " IdtBase: 0x%p \n " , Pcr - > IdtBase ) ;
KdbpPrint ( " Irql: %u \n " , Pcr - > Irql ) ;
KdbpPrint ( " SecondLevelCacheAssociativity: 0x%u \n " , Pcr - > SecondLevelCacheAssociativity ) ;
KdbpPrint ( " ObsoleteNumber: %u \n " , Pcr - > ObsoleteNumber ) ;
KdbpPrint ( " MajorVersion: 0x%x \n " , Pcr - > MajorVersion ) ;
KdbpPrint ( " MinorVersion: 0x%x \n " , Pcr - > MinorVersion ) ;
KdbpPrint ( " StallScaleFactor: 0x%lx \n " , Pcr - > StallScaleFactor ) ;
KdbpPrint ( " SecondLevelCacheSize: 0x%lx \n " , Pcr - > SecondLevelCacheSize ) ;
KdbpPrint ( " KdVersionBlock: 0x%p \n " , Pcr - > KdVersionBlock ) ;
2021-04-27 08:23:37 +00:00
# endif
2009-09-09 13:49:04 +00:00
return TRUE ;
2005-03-12 09:40:07 +00:00
}
2021-04-27 08:23:37 +00:00
# ifdef _M_IX86
2005-03-12 09:40:07 +00:00
/*!\brief Displays the TSS
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdTss (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2019-11-03 02:44:55 +00:00
USHORT TssSelector ;
PKTSS Tss = NULL ;
if ( Argc > = 2 )
{
/*
* Specified TSS via its selector [ selector ] or descriptor address [ * descaddr ] .
* Note that we ignore any other argument values .
*/
PCHAR Param , pszNext ;
ULONG ulValue ;
Param = Argv [ 1 ] ;
if ( Argv [ 1 ] [ 0 ] = = ' * ' )
+ + Param ;
ulValue = strtoul ( Param , & pszNext , 0 ) ;
if ( pszNext & & * pszNext )
{
KdbpPrint ( " Invalid TSS specification. \n " ) ;
return TRUE ;
}
if ( Argv [ 1 ] [ 0 ] = = ' * ' )
{
/* Descriptor specified */
TssSelector = 0 ; // Unknown selector!
// TODO: Room for improvement: Find the TSS descriptor
// in the GDT so as to validate it.
Tss = ( PKTSS ) ( ULONG_PTR ) ulValue ;
if ( ! Tss )
{
KdbpPrint ( " Invalid 32-bit TSS descriptor. \n " ) ;
return TRUE ;
}
}
else
{
/* Selector specified, retrive the corresponding TSS */
TssSelector = ( USHORT ) ulValue ;
Tss = KdbpRetrieveTss ( TssSelector , NULL , NULL ) ;
if ( ! Tss )
{
KdbpPrint ( " Invalid 32-bit TSS selector. \n " ) ;
return TRUE ;
}
}
}
if ( ! Tss )
{
/* If no TSS was specified, use the current TSS descriptor */
TssSelector = Ke386GetTr ( ) ;
Tss = KeGetPcr ( ) - > TSS ;
// NOTE: If everything works OK, Tss is the current TSS corresponding to the TR selector.
}
KdbpPrint ( " %s TSS 0x%04x is at 0x%p. \n " ,
( Tss = = KeGetPcr ( ) - > TSS ) ? " Current " : " Specified " , TssSelector , Tss ) ;
KdbpPrint ( " Backlink: 0x%04x \n "
" Ss0:Esp0: 0x%04x:0x%08x \n "
// NOTE: Ss1:Esp1 and Ss2:Esp2: are in the NotUsed1 field.
" CR3: 0x%08x \n "
" EFlags: 0x%08x \n "
" Eax: 0x%08x \n "
" Ebx: 0x%08x \n "
" Ecx: 0x%08x \n "
" Edx: 0x%08x \n "
" Esi: 0x%08x \n "
" Edi: 0x%08x \n "
" Eip: 0x%08x \n "
" Esp: 0x%08x \n "
" Ebp: 0x%08x \n "
" Cs: 0x%04x \n "
" Ss: 0x%04x \n "
" Ds: 0x%04x \n "
" Es: 0x%04x \n "
" Fs: 0x%04x \n "
" Gs: 0x%04x \n "
" LDT: 0x%04x \n "
" Flags: 0x%04x \n "
" IoMapBase: 0x%04x \n " ,
Tss - > Backlink , Tss - > Ss0 , Tss - > Esp0 , Tss - > CR3 , Tss - > EFlags ,
Tss - > Eax , Tss - > Ebx , Tss - > Ecx , Tss - > Edx , Tss - > Esi , Tss - > Edi ,
Tss - > Eip , Tss - > Esp , Tss - > Ebp ,
Tss - > Cs , Tss - > Ss , Tss - > Ds , Tss - > Es , Tss - > Fs , Tss - > Gs ,
Tss - > LDT , Tss - > Flags , Tss - > IoMapBase ) ;
2009-09-09 13:49:04 +00:00
return TRUE ;
2005-03-12 09:40:07 +00:00
}
2020-01-26 17:59:05 +00:00
# endif // _M_IX86
2005-03-12 09:40:07 +00:00
/*!\brief Bugchecks the system.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdBugCheck (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
/* Set the flag and quit looping */
KdbpBugCheckRequested = TRUE ;
return FALSE ;
2005-03-12 09:40:07 +00:00
}
2015-09-12 20:10:43 +00:00
static BOOLEAN
KdbpCmdReboot (
ULONG Argc ,
PCHAR Argv [ ] )
{
/* Reboot immediately (we do not return) */
HalReturnToFirmware ( HalRebootRoutine ) ;
return FALSE ;
}
2011-07-07 19:18:16 +00:00
/*!\brief Display debug messages on screen, with paging.
*
* Keys for per - page view : Home , End , PageUp , Arrow Up , PageDown ,
* all others are as PageDown .
*/
static BOOLEAN
KdbpCmdDmesg (
ULONG Argc ,
PCHAR Argv [ ] )
{
2019-11-03 01:14:17 +00:00
ULONG beg , end ;
KdbpIsInDmesgMode = TRUE ; /* Toggle logging flag */
if ( ! KdpDmesgBuffer )
{
KdbpPrint ( " Dmesg: error, buffer is not allocated! /DEBUGPORT=SCREEN kernel param required for dmesg. \n " ) ;
return TRUE ;
}
KdbpPrint ( " *** Dmesg *** TotalWritten=%lu, BufferSize=%lu, CurrentPosition=%lu \n " ,
KdbDmesgTotalWritten , KdpDmesgBufferSize , KdpDmesgCurrentPosition ) ;
/* Pass data to the pager */
end = KdpDmesgCurrentPosition ;
beg = ( end + KdpDmesgFreeBytes ) % KdpDmesgBufferSize ;
/* No roll-overs, and overwritten=lost bytes */
if ( KdbDmesgTotalWritten < = KdpDmesgBufferSize )
{
/* Show buffer (KdpDmesgBuffer + beg, num) */
KdbpPager ( KdpDmesgBuffer , KdpDmesgCurrentPosition ) ;
}
else
{
/* Show 2 buffers: (KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg)
* and : ( KdpDmesgBuffer , end ) */
KdbpPager ( KdpDmesgBuffer + beg , KdpDmesgBufferSize - beg ) ;
KdbpPrint ( " *** Dmesg: buffer rollup *** \n " ) ;
KdbpPager ( KdpDmesgBuffer , end ) ;
}
KdbpPrint ( " *** Dmesg: end of output *** \n " ) ;
KdbpIsInDmesgMode = FALSE ; /* Toggle logging flag */
2011-07-07 19:18:16 +00:00
return TRUE ;
}
2005-03-12 09:40:07 +00:00
/*!\brief Sets or displays a config variables value.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdSet (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
LONG l ;
BOOLEAN First ;
PCHAR pend = 0 ;
KDB_ENTER_CONDITION ConditionFirst = KdbDoNotEnter ;
KDB_ENTER_CONDITION ConditionLast = KdbDoNotEnter ;
static const PCHAR ExceptionNames [ 21 ] =
{
" ZERODEVIDE " , " DEBUGTRAP " , " NMI " , " INT3 " , " OVERFLOW " , " BOUND " , " INVALIDOP " ,
2005-03-12 09:40:07 +00:00
" NOMATHCOP " , " DOUBLEFAULT " , " RESERVED(9) " , " INVALIDTSS " , " SEGMENTNOTPRESENT " ,
" STACKFAULT " , " GPF " , " PAGEFAULT " , " RESERVED(15) " , " MATHFAULT " , " ALIGNMENTCHECK " ,
2009-09-09 13:49:04 +00:00
" MACHINECHECK " , " SIMDFAULT " , " OTHERS "
} ;
if ( Argc = = 1 )
{
KdbpPrint ( " Available settings: \n " ) ;
KdbpPrint ( " syntax [intel|at&t] \n " ) ;
KdbpPrint ( " condition [exception|*] [first|last] [never|always|kmode|umode] \n " ) ;
KdbpPrint ( " break_on_module_load [true|false] \n " ) ;
}
else if ( strcmp ( Argv [ 1 ] , " syntax " ) = = 0 )
{
if ( Argc = = 2 )
{
KdbpPrint ( " syntax = %s \n " , KdbUseIntelSyntax ? " intel " : " at&t " ) ;
}
else if ( Argc > = 3 )
{
if ( _stricmp ( Argv [ 2 ] , " intel " ) = = 0 )
KdbUseIntelSyntax = TRUE ;
else if ( _stricmp ( Argv [ 2 ] , " at&t " ) = = 0 )
KdbUseIntelSyntax = FALSE ;
else
KdbpPrint ( " Unknown syntax '%s'. \n " , Argv [ 2 ] ) ;
}
}
else if ( strcmp ( Argv [ 1 ] , " condition " ) = = 0 )
{
if ( Argc = = 2 )
{
KdbpPrint ( " Conditions: (First) (Last) \n " ) ;
for ( l = 0 ; l < RTL_NUMBER_OF ( ExceptionNames ) - 1 ; l + + )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
if ( ! ExceptionNames [ l ] )
continue ;
if ( ! KdbpGetEnterCondition ( l , TRUE , & ConditionFirst ) )
2019-11-03 01:14:17 +00:00
ASSERT ( FALSE ) ;
2009-09-09 13:49:04 +00:00
if ( ! KdbpGetEnterCondition ( l , FALSE , & ConditionLast ) )
2019-11-03 01:14:17 +00:00
ASSERT ( FALSE ) ;
2009-09-09 13:49:04 +00:00
KdbpPrint ( " #%02d %-20s %-8s %-8s \n " , l , ExceptionNames [ l ] ,
KDB_ENTER_CONDITION_TO_STRING ( ConditionFirst ) ,
KDB_ENTER_CONDITION_TO_STRING ( ConditionLast ) ) ;
2005-03-12 09:40:07 +00:00
}
2009-09-09 13:49:04 +00:00
ASSERT ( l = = ( RTL_NUMBER_OF ( ExceptionNames ) - 1 ) ) ;
KdbpPrint ( " %-20s %-8s %-8s \n " , ExceptionNames [ l ] ,
KDB_ENTER_CONDITION_TO_STRING ( ConditionFirst ) ,
KDB_ENTER_CONDITION_TO_STRING ( ConditionLast ) ) ;
}
else
{
if ( Argc > = 5 & & strcmp ( Argv [ 2 ] , " * " ) = = 0 ) /* Allow * only when setting condition */
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
l = - 1 ;
2005-03-12 09:40:07 +00:00
}
else
{
2009-09-09 13:49:04 +00:00
l = strtoul ( Argv [ 2 ] , & pend , 0 ) ;
if ( Argv [ 2 ] = = pend )
{
for ( l = 0 ; l < RTL_NUMBER_OF ( ExceptionNames ) ; l + + )
{
if ( ! ExceptionNames [ l ] )
continue ;
if ( _stricmp ( ExceptionNames [ l ] , Argv [ 2 ] ) = = 0 )
break ;
}
}
if ( l > = RTL_NUMBER_OF ( ExceptionNames ) )
{
KdbpPrint ( " Unknown exception '%s'. \n " , Argv [ 2 ] ) ;
return TRUE ;
}
2005-03-12 09:40:07 +00:00
}
2009-09-09 13:49:04 +00:00
if ( Argc > 4 )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
if ( _stricmp ( Argv [ 3 ] , " first " ) = = 0 )
First = TRUE ;
else if ( _stricmp ( Argv [ 3 ] , " last " ) = = 0 )
First = FALSE ;
else
{
KdbpPrint ( " set condition: second argument must be 'first' or 'last' \n " ) ;
return TRUE ;
}
if ( _stricmp ( Argv [ 4 ] , " never " ) = = 0 )
ConditionFirst = KdbDoNotEnter ;
else if ( _stricmp ( Argv [ 4 ] , " always " ) = = 0 )
ConditionFirst = KdbEnterAlways ;
else if ( _stricmp ( Argv [ 4 ] , " umode " ) = = 0 )
ConditionFirst = KdbEnterFromUmode ;
else if ( _stricmp ( Argv [ 4 ] , " kmode " ) = = 0 )
ConditionFirst = KdbEnterFromKmode ;
else
{
KdbpPrint ( " set condition: third argument must be 'never', 'always', 'umode' or 'kmode' \n " ) ;
return TRUE ;
}
if ( ! KdbpSetEnterCondition ( l , First , ConditionFirst ) )
{
if ( l > = 0 )
KdbpPrint ( " Couldn't change condition for exception #%02d \n " , l ) ;
else
KdbpPrint ( " Couldn't change condition for all exceptions \n " , l ) ;
}
2005-03-12 09:40:07 +00:00
}
2009-09-09 13:49:04 +00:00
else /* Argc >= 3 */
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
if ( ! KdbpGetEnterCondition ( l , TRUE , & ConditionFirst ) )
2019-11-03 01:14:17 +00:00
ASSERT ( FALSE ) ;
2009-09-09 13:49:04 +00:00
if ( ! KdbpGetEnterCondition ( l , FALSE , & ConditionLast ) )
2019-11-03 01:14:17 +00:00
ASSERT ( FALSE ) ;
2009-09-09 13:49:04 +00:00
if ( l < ( RTL_NUMBER_OF ( ExceptionNames ) - 1 ) )
{
KdbpPrint ( " Condition for exception #%02d (%s): FirstChance %s LastChance %s \n " ,
l , ExceptionNames [ l ] ,
KDB_ENTER_CONDITION_TO_STRING ( ConditionFirst ) ,
KDB_ENTER_CONDITION_TO_STRING ( ConditionLast ) ) ;
}
else
{
KdbpPrint ( " Condition for all other exceptions: FirstChance %s LastChance %s \n " ,
KDB_ENTER_CONDITION_TO_STRING ( ConditionFirst ) ,
KDB_ENTER_CONDITION_TO_STRING ( ConditionLast ) ) ;
}
2005-03-12 09:40:07 +00:00
}
2009-09-09 13:49:04 +00:00
}
}
else if ( strcmp ( Argv [ 1 ] , " break_on_module_load " ) = = 0 )
{
if ( Argc = = 2 )
KdbpPrint ( " break_on_module_load = %s \n " , KdbBreakOnModuleLoad ? " enabled " : " disabled " ) ;
else if ( Argc > = 3 )
{
if ( _stricmp ( Argv [ 2 ] , " enable " ) = = 0 | | _stricmp ( Argv [ 2 ] , " enabled " ) = = 0 | | _stricmp ( Argv [ 2 ] , " true " ) = = 0 )
KdbBreakOnModuleLoad = TRUE ;
else if ( _stricmp ( Argv [ 2 ] , " disable " ) = = 0 | | _stricmp ( Argv [ 2 ] , " disabled " ) = = 0 | | _stricmp ( Argv [ 2 ] , " false " ) = = 0 )
KdbBreakOnModuleLoad = FALSE ;
2005-03-12 09:40:07 +00:00
else
2009-09-09 13:49:04 +00:00
KdbpPrint ( " Unknown setting '%s'. \n " , Argv [ 2 ] ) ;
}
}
else
{
KdbpPrint ( " Unknown setting '%s'. \n " , Argv [ 1 ] ) ;
}
return TRUE ;
2005-03-12 09:40:07 +00:00
}
/*!\brief Displays help screen.
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2009-09-09 13:49:04 +00:00
KdbpCmdHelp (
ULONG Argc ,
PCHAR Argv [ ] )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
ULONG i ;
KdbpPrint ( " Kernel debugger commands: \n " ) ;
for ( i = 0 ; i < RTL_NUMBER_OF ( KdbDebuggerCommands ) ; i + + )
{
if ( ! KdbDebuggerCommands [ i ] . Syntax ) /* Command group */
{
if ( i > 0 )
KdbpPrint ( " \n " ) ;
2005-03-12 09:40:07 +00:00
2009-09-09 13:49:04 +00:00
KdbpPrint ( " \x1b [7m* %s: \x1b [0m \n " , KdbDebuggerCommands [ i ] . Help ) ;
continue ;
}
KdbpPrint ( " %-20s - %s \n " ,
KdbDebuggerCommands [ i ] . Syntax ,
KdbDebuggerCommands [ i ] . Help ) ;
}
2005-03-12 09:40:07 +00:00
2009-09-09 13:49:04 +00:00
return TRUE ;
2005-03-12 09:40:07 +00:00
}
2009-09-09 13:49:04 +00:00
2011-07-07 19:18:16 +00:00
/*
2022-11-21 15:35:47 +00:00
* memrchr ( ) , explicitly defined , since absent in the CRT .
2011-07-07 19:18:16 +00:00
* Reverse memchr ( )
* Find the last occurrence of ' c ' in the buffer ' s ' of size ' n ' .
*/
void *
memrchr ( const void * s , int c , size_t n )
{
const unsigned char * cp ;
if ( n ! = 0 )
{
cp = ( unsigned char * ) s + n ;
do
{
if ( * ( - - cp ) = = ( unsigned char ) c )
return ( void * ) cp ;
} while ( - - n ! = 0 ) ;
}
return NULL ;
}
2023-03-29 00:06:35 +00:00
/**
* @ brief Calculate pointer position for N lines above the current position .
2011-07-07 19:18:16 +00:00
*
2023-03-29 00:06:35 +00:00
* Calculate pointer position for N lines above the current displaying
* position within the given buffer . Used by KdbpPager ( ) .
2011-07-07 19:18:16 +00:00
*
2023-03-29 00:06:35 +00:00
* @ param [ in ] Buffer
* Character buffer to operate on .
2011-07-07 19:18:16 +00:00
*
2023-03-29 00:06:35 +00:00
* @ param [ in ] BufLength
* Size of the buffer .
*
* @ param [ in ] pCurPos
* Current position within the buffer .
*
* @ return Beginning of the previous page of text .
*
* @ note N lines count is hardcoded to the terminal ' s number of rows .
* */
2022-11-21 15:35:47 +00:00
static PCHAR
CountOnePageUp (
_In_ PCCH Buffer ,
_In_ ULONG BufLength ,
2023-03-29 00:06:35 +00:00
_In_ PCCH pCurPos ,
_In_ const SIZE * TermSize )
2011-07-07 19:18:16 +00:00
{
2022-11-21 15:35:47 +00:00
PCCH p ;
2011-07-07 19:18:16 +00:00
// p0 is initial guess of Page Start
2023-03-29 00:06:35 +00:00
ULONG p0len = TermSize - > cx * TermSize - > cy ;
2022-11-21 15:35:47 +00:00
PCCH p0 = pCurPos - p0len ;
PCCH prev_p = p0 , p1 ;
2011-07-07 19:18:16 +00:00
ULONG j ;
if ( pCurPos < Buffer )
pCurPos = Buffer ;
ASSERT ( pCurPos < = Buffer + BufLength ) ;
p = memrchr ( p0 , ' \n ' , p0len ) ;
2022-11-21 15:35:47 +00:00
if ( ! p )
2011-07-07 19:18:16 +00:00
p = p0 ;
2023-03-29 00:06:35 +00:00
for ( j = TermSize - > cy ; j - - ; )
2011-07-07 19:18:16 +00:00
{
2011-08-10 16:12:45 +00:00
int linesCnt ;
2011-07-07 19:18:16 +00:00
p1 = memrchr ( p0 , ' \n ' , p - p0 ) ;
prev_p = p ;
p = p1 ;
2022-11-21 15:35:47 +00:00
if ( ! p )
2011-07-07 19:18:16 +00:00
{
p = prev_p ;
2022-11-21 15:35:47 +00:00
if ( ! p )
2011-07-07 19:18:16 +00:00
p = p0 ;
break ;
}
2023-03-29 00:06:35 +00:00
linesCnt = ( TermSize - > cx + prev_p - p - 2 ) / TermSize - > cx ;
2011-07-07 19:18:16 +00:00
if ( linesCnt > 1 )
j - = linesCnt - 1 ;
}
2022-11-21 15:35:47 +00:00
ASSERT ( p ! = NULL ) ;
2011-07-07 19:18:16 +00:00
+ + p ;
2022-11-21 15:35:47 +00:00
return ( PCHAR ) p ;
}
static VOID
KdpFilterEscapes (
_Inout_ PSTR String )
{
PCHAR p ;
SIZE_T i ;
size_t len ;
while ( ( p = strrchr ( String , ' \x1b ' ) ) ) /* Look for escape character */
{
len = strlen ( p ) ;
if ( p [ 1 ] = = ' [ ' )
{
i = 2 ;
while ( ! isalpha ( p [ i + + ] ) ) ;
memmove ( p , p + i , len + 1 - i ) ;
}
else
{
memmove ( p , p + 1 , len ) ;
}
}
2011-07-07 19:18:16 +00:00
}
/*!\brief Prints the given string with, page by page.
*
* \ param Buffer Characters buffer to print .
* \ param BufferLen Buffer size .
*
* \ note Doesn ' t correctly handle \ \ t and terminal escape sequences when calculating the
* number of lines required to print a single line from the Buffer in the terminal .
* Maximum length of buffer is limited only by memory size .
2023-03-29 17:38:10 +00:00
* Uses KdbPrintf internally .
2011-07-07 19:18:16 +00:00
*
2023-03-29 00:06:35 +00:00
* Note : BufLength should be greater than ( KdTermSize . cx * KdTermSize . cy ) .
2011-07-07 19:18:16 +00:00
*/
2023-03-29 00:06:35 +00:00
static VOID
2022-11-21 15:35:47 +00:00
KdbpPagerInternal (
_In_ PCHAR Buffer ,
_In_ ULONG BufLength ,
_In_ BOOLEAN DoPage )
2011-07-07 19:18:16 +00:00
{
static BOOLEAN TerminalInitialized = FALSE ;
2022-11-21 15:35:47 +00:00
CHAR c ;
ULONG ScanCode ;
PCHAR p ;
SIZE_T i ;
2011-07-07 19:18:16 +00:00
LONG RowsPrintedByTerminal ;
2022-11-21 15:35:47 +00:00
if ( BufLength = = 0 )
2023-03-29 00:06:35 +00:00
return ;
2011-07-07 19:18:16 +00:00
/* Check if the user has aborted output of the current command */
if ( KdbOutputAborted )
return ;
/* Initialize the terminal */
if ( ! TerminalInitialized )
{
2022-11-21 15:35:47 +00:00
TerminalInitialized = TRUE ;
2023-03-29 00:06:35 +00:00
KdpInitTerminal ( ) ;
2011-07-07 19:18:16 +00:00
}
2024-10-14 18:29:46 +00:00
/* Refresh terminal size each time when number of printed rows is 0 */
2023-03-29 00:06:35 +00:00
if ( KdbNumberOfRowsPrinted = = 0 )
2011-07-07 19:18:16 +00:00
{
2023-03-29 00:06:35 +00:00
KdpUpdateTerminalSize ( & KdTermSize ) ;
2011-07-07 19:18:16 +00:00
}
2022-11-21 15:35:47 +00:00
/* Loop through the strings */
2011-07-07 19:18:16 +00:00
p = Buffer ;
while ( p [ 0 ] ! = ' \0 ' )
{
2022-11-21 15:35:47 +00:00
if ( DoPage )
2011-07-07 19:18:16 +00:00
{
2022-11-21 15:35:47 +00:00
if ( p > Buffer + BufLength )
{
2023-03-29 17:38:10 +00:00
KdbPrintf ( " Dmesg: error, p > Buffer+BufLength,d=%d " , p - ( Buffer + BufLength ) ) ;
2022-11-21 15:35:47 +00:00
return ;
}
2011-07-07 19:18:16 +00:00
}
i = strcspn ( p , " \n " ) ;
2022-11-21 15:35:47 +00:00
if ( DoPage )
{
/* Are we out of buffer? */
if ( p + i > Buffer + BufLength )
break ; // Leaving pager function
}
2011-07-07 19:18:16 +00:00
2022-11-21 15:35:47 +00:00
/* Calculate the number of lines which will be printed in
* the terminal when outputting the current line . */
2011-07-07 19:18:16 +00:00
if ( i > 0 )
2023-03-29 00:06:35 +00:00
RowsPrintedByTerminal = ( i + KdbNumberOfColsPrinted - 1 ) / KdTermSize . cx ;
2011-07-07 19:18:16 +00:00
else
RowsPrintedByTerminal = 0 ;
if ( p [ i ] = = ' \n ' )
RowsPrintedByTerminal + + ;
2023-03-29 17:38:10 +00:00
//KdbPrintf("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);
2011-07-07 19:18:16 +00:00
/* Display a prompt if we printed one screen full of text */
2023-03-29 00:06:35 +00:00
if ( KdTermSize . cy > 0 & &
( LONG ) ( KdbNumberOfRowsPrinted + RowsPrintedByTerminal ) > = KdTermSize . cy )
2011-07-07 19:18:16 +00:00
{
2023-03-29 17:38:10 +00:00
PCSTR Prompt ;
2023-03-29 00:06:35 +00:00
/* Disable the repetition of previous command with long many-page output */
2011-11-21 05:28:08 +00:00
KdbRepeatLastCommand = FALSE ;
2011-07-07 19:18:16 +00:00
if ( KdbNumberOfColsPrinted > 0 )
2023-03-29 17:38:10 +00:00
KdbPuts ( " \n " ) ;
2011-07-07 19:18:16 +00:00
2022-11-21 15:35:47 +00:00
if ( DoPage )
2023-03-29 17:38:10 +00:00
Prompt = " --- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn --- " ;
2022-11-21 15:35:47 +00:00
else
2023-03-29 17:38:10 +00:00
Prompt = " --- Press q to abort, any other key to continue --- " ;
2011-07-07 19:18:16 +00:00
2023-03-29 17:38:10 +00:00
KdbPuts ( Prompt ) ;
2023-03-29 00:06:35 +00:00
c = KdpReadTermKey ( & ScanCode ) ;
2023-03-29 17:38:10 +00:00
if ( DoPage ) // Show pressed key
KdbPrintf ( " '%c'/scan=%04x \n " , c , ScanCode ) ;
2022-11-21 15:35:47 +00:00
else
2023-03-29 17:38:10 +00:00
KdbPuts ( " \n " ) ;
RowsPrintedByTerminal + + ;
2022-11-21 15:35:47 +00:00
if ( c = = ' q ' )
2011-07-07 19:18:16 +00:00
{
2022-11-21 15:35:47 +00:00
KdbOutputAborted = TRUE ;
return ;
2011-07-07 19:18:16 +00:00
}
2022-11-21 15:35:47 +00:00
if ( DoPage )
2011-07-07 19:18:16 +00:00
{
2022-11-21 15:35:47 +00:00
if ( ScanCode = = KEYSC_END | | c = = ' e ' )
{
PCHAR pBufEnd = Buffer + BufLength ;
2023-03-29 00:06:35 +00:00
p = CountOnePageUp ( Buffer , BufLength , pBufEnd , & KdTermSize ) ;
2022-11-21 15:35:47 +00:00
i = strcspn ( p , " \n " ) ;
}
2023-03-28 12:13:48 +00:00
else if ( ScanCode = = KEYSC_PAGEUP | |
ScanCode = = KEYSC_ARROWUP | | c = = ' u ' )
2022-11-21 15:35:47 +00:00
{
2023-03-29 00:06:35 +00:00
p = CountOnePageUp ( Buffer , BufLength , p , & KdTermSize ) ;
2022-11-21 15:35:47 +00:00
i = strcspn ( p , " \n " ) ;
}
else if ( ScanCode = = KEYSC_HOME | | c = = ' h ' )
{
p = Buffer ;
i = strcspn ( p , " \n " ) ;
}
2011-07-07 19:18:16 +00:00
}
KdbNumberOfRowsPrinted = 0 ;
KdbNumberOfColsPrinted = 0 ;
}
2022-11-21 15:35:47 +00:00
/* Insert a NUL after the line and print only the current line */
2011-07-07 19:18:16 +00:00
if ( p [ i ] = = ' \n ' & & p [ i + 1 ] ! = ' \0 ' )
{
c = p [ i + 1 ] ;
p [ i + 1 ] = ' \0 ' ;
}
else
{
c = ' \0 ' ;
}
2022-11-21 15:35:47 +00:00
/* Remove escape sequences from the line if there is no terminal connected */
// FIXME: Dangerous operation since we modify the source string!!
2023-03-29 00:06:35 +00:00
if ( ! KdTermConnected )
2022-11-21 15:35:47 +00:00
KdpFilterEscapes ( p ) ;
2011-07-07 19:18:16 +00:00
2022-11-21 15:35:47 +00:00
/* Print the current line */
2023-03-29 17:38:10 +00:00
KdbPuts ( p ) ;
2011-07-07 19:18:16 +00:00
2022-11-21 15:35:47 +00:00
/* Restore not null char with saved */
2011-07-07 19:18:16 +00:00
if ( c ! = ' \0 ' )
p [ i + 1 ] = c ;
/* Set p to the start of the next line and
2024-10-14 18:29:46 +00:00
* remember the number of printed rows / cols */
2011-07-07 19:18:16 +00:00
p + = i ;
if ( p [ 0 ] = = ' \n ' )
{
p + + ;
KdbNumberOfColsPrinted = 0 ;
}
else
{
ASSERT ( p [ 0 ] = = ' \0 ' ) ;
KdbNumberOfColsPrinted + = i ;
}
2009-09-09 13:49:04 +00:00
KdbNumberOfRowsPrinted + = RowsPrintedByTerminal ;
}
2005-03-12 09:40:07 +00:00
}
2022-11-21 15:35:47 +00:00
/*!\brief Prints the given string with, page by page.
*
* \ param Buffer Characters buffer to print .
* \ param BufferLen Buffer size .
*
* \ note Doesn ' t correctly handle \ \ t and terminal escape sequences when calculating the
* number of lines required to print a single line from the Buffer in the terminal .
* Maximum length of buffer is limited only by memory size .
2023-03-29 17:38:10 +00:00
* Uses KdbPrintf internally .
2022-11-21 15:35:47 +00:00
*
2023-03-29 00:06:35 +00:00
* Note : BufLength should be greater than ( KdTermSize . cx * KdTermSize . cy ) .
2022-11-21 15:35:47 +00:00
*/
VOID
KdbpPager (
_In_ PCHAR Buffer ,
_In_ ULONG BufLength )
{
/* Call the internal function */
KdbpPagerInternal ( Buffer , BufLength , TRUE ) ;
}
/*!\brief Prints the given string with printf-like formatting.
*
* \ param Format Format of the string / arguments .
* \ param . . . Variable number of arguments matching the format specified in \ a Format .
*
* \ note Doesn ' t correctly handle \ \ t and terminal escape sequences when calculating the
* number of lines required to print a single line from the Buffer in the terminal .
* Prints maximum 4096 chars , because of its buffer size .
*/
VOID
KdbpPrint (
_In_ PSTR Format ,
_In_ . . . )
{
static CHAR Buffer [ 4096 ] ;
ULONG Length ;
va_list ap ;
/* Check if the user has aborted output of the current command */
if ( KdbOutputAborted )
return ;
/* Build the string */
va_start ( ap , Format ) ;
Length = _vsnprintf ( Buffer , sizeof ( Buffer ) - 1 , Format , ap ) ;
Buffer [ Length ] = ' \0 ' ;
va_end ( ap ) ;
/* Actually print it */
KdbpPagerInternal ( Buffer , Length , FALSE ) ;
}
VOID
KdbpPrintUnicodeString (
_In_ PCUNICODE_STRING String )
{
ULONG i ;
if ( ( String = = NULL ) | | ( String - > Buffer = = NULL ) )
{
KdbpPrint ( " <NULL> " ) ;
return ;
}
for ( i = 0 ; i < String - > Length / sizeof ( WCHAR ) ; i + + )
{
KdbpPrint ( " %c " , ( CHAR ) String - > Buffer [ i ] ) ;
}
}
2012-10-01 23:06:32 +00:00
BOOLEAN
NTAPI
KdbRegisterCliCallback (
PVOID Callback ,
BOOLEAN Deregister )
{
ULONG i ;
/* Loop all entries */
for ( i = 0 ; i < _countof ( KdbCliCallbacks ) ; i + + )
{
/* Check if deregistering was requested */
if ( Deregister )
{
/* Check if this entry is the one that was registered */
if ( KdbCliCallbacks [ i ] = = Callback )
{
/* Delete it and report success */
KdbCliCallbacks [ i ] = NULL ;
return TRUE ;
}
}
else
{
/* Check if this entry is free */
if ( KdbCliCallbacks [ i ] = = NULL )
{
/* Set it and and report success */
KdbCliCallbacks [ i ] = Callback ;
return TRUE ;
}
}
}
/* Unsuccessful */
return FALSE ;
}
/*! \brief Invokes registered CLI callbacks until one of them handled the
* Command .
*
* \ param Command - Command line to parse and execute if possible .
* \ param Argc - Number of arguments in Argv
* \ param Argv - Array of strings , each of them containing one argument .
*
* \ return TRUE , if the command was handled , FALSE if it was not handled .
*/
static
BOOLEAN
KdbpInvokeCliCallbacks (
IN PCHAR Command ,
IN ULONG Argc ,
2019-11-18 00:34:19 +00:00
IN PCHAR Argv [ ] )
2012-10-01 23:06:32 +00:00
{
ULONG i ;
/* Loop all entries */
for ( i = 0 ; i < _countof ( KdbCliCallbacks ) ; i + + )
{
/* Check if this entry is registered */
if ( KdbCliCallbacks [ i ] )
{
/* Invoke the callback and check if it handled the command */
if ( KdbCliCallbacks [ i ] ( Command , Argc , Argv ) )
{
return TRUE ;
}
}
}
/* None of the callbacks handled the command */
return FALSE ;
}
2005-03-12 09:40:07 +00:00
/*!\brief Parses command line and executes command if found
*
* \ param Command Command line to parse and execute if possible .
*
* \ retval TRUE Don ' t continue execution .
* \ retval FALSE Continue execution ( leave KDB )
*/
2009-06-13 15:28:33 +00:00
static BOOLEAN
2005-03-12 09:40:07 +00:00
KdbpDoCommand (
2009-09-09 13:49:04 +00:00
IN PCHAR Command )
2005-03-12 09:40:07 +00:00
{
2024-10-14 18:29:46 +00:00
BOOLEAN Continue = TRUE ;
2020-01-26 17:59:05 +00:00
SIZE_T i ;
2009-09-09 13:49:04 +00:00
PCHAR p ;
ULONG Argc ;
2012-10-01 23:06:32 +00:00
// FIXME: for what do we need a 1024 characters command line and 256 tokens?
2019-11-18 00:34:19 +00:00
static PCHAR Argv [ 256 ] ;
2009-09-09 13:49:04 +00:00
static CHAR OrigCommand [ 1024 ] ;
2011-03-25 22:28:15 +00:00
RtlStringCbCopyA ( OrigCommand , sizeof ( OrigCommand ) , Command ) ;
2009-09-09 13:49:04 +00:00
Argc = 0 ;
p = Command ;
for ( ; ; )
{
while ( * p = = ' \t ' | | * p = = ' ' )
p + + ;
if ( * p = = ' \0 ' )
break ;
i = strcspn ( p , " \t " ) ;
Argv [ Argc + + ] = p ;
p + = i ;
if ( * p = = ' \0 ' )
break ;
* p = ' \0 ' ;
p + + ;
}
if ( Argc < 1 )
return TRUE ;
2024-10-14 18:29:46 +00:00
/* Reset the pager state: number of printed rows/cols and aborted output flag */
KdbNumberOfRowsPrinted = KdbNumberOfColsPrinted = 0 ;
KdbOutputAborted = FALSE ;
2009-09-09 13:49:04 +00:00
for ( i = 0 ; i < RTL_NUMBER_OF ( KdbDebuggerCommands ) ; i + + )
{
if ( ! KdbDebuggerCommands [ i ] . Name )
continue ;
if ( strcmp ( KdbDebuggerCommands [ i ] . Name , Argv [ 0 ] ) = = 0 )
{
2024-10-14 18:29:46 +00:00
Continue = KdbDebuggerCommands [ i ] . Fn ( Argc , Argv ) ;
goto Done ;
2009-09-09 13:49:04 +00:00
}
}
2012-10-01 23:06:32 +00:00
/* Now invoke the registered callbacks */
if ( KdbpInvokeCliCallbacks ( Command , Argc , Argv ) )
2024-10-14 18:29:46 +00:00
goto Done ;
2012-10-01 23:06:32 +00:00
2024-10-14 18:29:46 +00:00
KdbPrintf ( " Command '%s' is unknown. \n " , OrigCommand ) ;
Done :
KdbOutputAborted = FALSE ;
return Continue ;
2005-03-12 09:40:07 +00:00
}
/*!\brief KDB Main Loop.
*
* \ param EnteredOnSingleStep TRUE if KDB was entered on single step .
*/
VOID
KdbpCliMainLoop (
2009-09-09 13:49:04 +00:00
IN BOOLEAN EnteredOnSingleStep )
2005-03-12 09:40:07 +00:00
{
2024-10-14 18:29:46 +00:00
BOOLEAN Continue = TRUE ;
2023-03-20 16:49:15 +00:00
static CHAR Command [ 1024 ] ;
static CHAR LastCommand [ 1024 ] = " " ;
2009-09-09 13:49:04 +00:00
2024-10-14 21:36:20 +00:00
// FIXME HACK: SYSREG SUPPORT CORE-19807 -- Emit a backtrace.
// TODO: Remove once SYSREG "bt" command emission is fixed!
# if 1
KdbpDoCommand ( " bt " ) ;
# endif
2009-09-09 13:49:04 +00:00
if ( EnteredOnSingleStep )
{
2021-04-27 08:23:37 +00:00
if ( ! KdbSymPrintAddress ( ( PVOID ) KeGetContextPc ( KdbCurrentTrapFrame ) , KdbCurrentTrapFrame ) )
2024-10-14 18:29:46 +00:00
KdbPrintf ( " <%p> " , KeGetContextPc ( KdbCurrentTrapFrame ) ) ;
2009-09-09 13:49:04 +00:00
2024-10-14 18:29:46 +00:00
KdbPuts ( " : " ) ;
2021-04-27 08:23:37 +00:00
if ( KdbpDisassemble ( KeGetContextPc ( KdbCurrentTrapFrame ) , KdbUseIntelSyntax ) < 0 )
2024-10-14 18:29:46 +00:00
KdbPuts ( " <INVALID> " ) ;
KdbPuts ( " \n " ) ;
}
else
{
/* Preceding this message is one of the "Entered debugger..." banners */
// KdbPuts("\nEntered debugger\n");
KdbPuts ( " \n Type \" help \" for a list of commands. \n " ) ;
2009-09-09 13:49:04 +00:00
}
/* Main loop */
2024-10-14 18:29:46 +00:00
while ( Continue )
2009-09-09 13:49:04 +00:00
{
2023-03-20 16:49:15 +00:00
/*
2023-03-29 17:38:10 +00:00
* Print the prompt and read a command .
* Repeat the last one if the user pressed Enter .
2023-03-20 16:49:15 +00:00
* This reduces the risk of RSI when single - stepping !
*/
2023-08-29 20:32:29 +00:00
// TEMP HACK! Issue an empty string instead of duplicating "kdb:>"
2024-10-14 18:29:46 +00:00
SIZE_T CmdLen = KdbPrompt ( /*KdbPromptStr.Buffer*/ " " , Command , sizeof ( Command ) ) ;
2023-03-29 17:38:10 +00:00
if ( CmdLen = = 0 )
{
/* Nothing received but the user didn't press Enter, retry */
continue ;
}
else if ( CmdLen > 1 ) // i.e. (*Command != ANSI_NULL)
2023-03-20 16:49:15 +00:00
{
/* Save this new last command */
KdbRepeatLastCommand = TRUE ;
RtlStringCbCopyA ( LastCommand , sizeof ( LastCommand ) , Command ) ;
2009-09-09 13:49:04 +00:00
2023-03-20 16:49:15 +00:00
/* Remember it */
KdbpCommandHistoryAppend ( Command ) ;
}
else if ( KdbRepeatLastCommand )
{
/* The user directly pressed Enter */
RtlStringCbCopyA ( Command , sizeof ( Command ) , LastCommand ) ;
}
2009-09-09 13:49:04 +00:00
2024-10-14 18:29:46 +00:00
/* Invoke the command */
2009-09-09 13:49:04 +00:00
Continue = KdbpDoCommand ( Command ) ;
}
2005-03-12 09:40:07 +00:00
}
2022-11-28 02:13:31 +00:00
/**
* @ brief
* Interprets the KDBinit file from the \ SystemRoot \ System32 \ drivers \ etc
* directory , that has been loaded by KdbpCliInit ( ) .
2005-03-12 09:40:07 +00:00
*
2022-11-28 02:13:31 +00:00
* This function is used to interpret the init file in the debugger context
* with a trap frame set up . KdbpCliInit ( ) enters the debugger by calling
* DbgBreakPointWithStatus ( DBG_STATUS_CONTROL_C ) . In turn , this will call
* KdbEnterDebuggerException ( ) which will finally call this function if
* KdbInitFileBuffer is not NULL .
* */
2005-03-12 09:40:07 +00:00
VOID
2015-09-03 23:57:39 +00:00
KdbpCliInterpretInitFile ( VOID )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
PCHAR p1 , p2 ;
2022-11-28 02:13:31 +00:00
p1 = InterlockedExchangePointer ( ( PVOID * ) & KdbInitFileBuffer , NULL ) ;
if ( ! p1 )
return ;
2009-09-09 13:49:04 +00:00
/* Execute the commands in the init file */
2022-11-28 02:13:31 +00:00
KdbPuts ( " KDB: Executing KDBinit file... \n " ) ;
2009-09-09 13:49:04 +00:00
while ( p1 [ 0 ] ! = ' \0 ' )
{
2024-10-14 18:27:38 +00:00
size_t i = strcspn ( p1 , " \r \n " ) ;
2009-09-09 13:49:04 +00:00
if ( i > 0 )
{
2024-10-14 18:27:38 +00:00
CHAR c = p1 [ i ] ;
2009-09-09 13:49:04 +00:00
p1 [ i ] = ' \0 ' ;
/* Look for "break" command and comments */
p2 = p1 ;
while ( isspace ( p2 [ 0 ] ) )
p2 + + ;
if ( strncmp ( p2 , " break " , sizeof ( " break " ) - 1 ) = = 0 & &
( p2 [ sizeof ( " break " ) - 1 ] = = ' \0 ' | | isspace ( p2 [ sizeof ( " break " ) - 1 ] ) ) )
{
2022-11-28 02:13:31 +00:00
/* Run the interactive debugger loop */
2009-09-09 13:49:04 +00:00
KdbpCliMainLoop ( FALSE ) ;
}
else if ( p2 [ 0 ] ! = ' # ' & & p2 [ 0 ] ! = ' \0 ' ) /* Ignore empty lines and comments */
{
2022-11-28 02:13:31 +00:00
/* Invoke the command */
2009-09-09 13:49:04 +00:00
KdbpDoCommand ( p1 ) ;
}
p1 [ i ] = c ;
}
p1 + = i ;
while ( p1 [ 0 ] = = ' \r ' | | p1 [ 0 ] = = ' \n ' )
p1 + + ;
}
2022-11-28 02:13:31 +00:00
KdbPuts ( " KDB: KDBinit executed \n " ) ;
2005-03-12 09:40:07 +00:00
}
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
/**
* @ brief Called when KDB is initialized .
2005-03-12 09:40:07 +00:00
*
2022-11-28 02:13:31 +00:00
* Loads the KDBinit file from the \ SystemRoot \ System32 \ drivers \ etc
* directory and interprets it , by calling back into the debugger .
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
* */
NTSTATUS
2015-09-03 23:57:39 +00:00
KdbpCliInit ( VOID )
2005-03-12 09:40:07 +00:00
{
2009-09-09 13:49:04 +00:00
NTSTATUS Status ;
OBJECT_ATTRIBUTES ObjectAttributes ;
UNICODE_STRING FileName ;
IO_STATUS_BLOCK Iosb ;
FILE_STANDARD_INFORMATION FileStdInfo ;
HANDLE hFile = NULL ;
2022-11-28 02:13:31 +00:00
ULONG FileSize ;
2009-09-09 13:49:04 +00:00
PCHAR FileBuffer ;
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
/* Don't load the KDBinit file if its buffer is already lying around */
if ( KdbInitFileBuffer )
return STATUS_SUCCESS ;
2009-09-09 13:49:04 +00:00
/* Initialize the object attributes */
2015-03-16 00:25:32 +00:00
RtlInitUnicodeString ( & FileName , L " \\ SystemRoot \\ System32 \\ drivers \\ etc \\ KDBinit " ) ;
2020-09-09 01:46:56 +00:00
InitializeObjectAttributes ( & ObjectAttributes ,
& FileName ,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE ,
NULL ,
NULL ) ;
2009-09-09 13:49:04 +00:00
/* Open the file */
2013-07-19 15:05:28 +00:00
Status = ZwOpenFile ( & hFile , FILE_READ_DATA | SYNCHRONIZE ,
& ObjectAttributes , & Iosb , 0 ,
2009-09-09 13:49:04 +00:00
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
FILE_NO_INTERMEDIATE_BUFFERING ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2022-11-28 02:13:31 +00:00
DPRINT ( " Could not open %wZ (Status 0x%lx) \n " , & FileName , Status ) ;
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
return Status ;
2009-09-09 13:49:04 +00:00
}
/* Get the size of the file */
2023-01-09 11:11:19 +00:00
Status = ZwQueryInformationFile ( hFile , & Iosb ,
& FileStdInfo , sizeof ( FileStdInfo ) ,
2009-09-09 13:49:04 +00:00
FileStandardInformation ) ;
if ( ! NT_SUCCESS ( Status ) )
{
ZwClose ( hFile ) ;
2022-11-28 02:13:31 +00:00
DPRINT1 ( " Could not query size of %wZ (Status 0x%lx) \n " , & FileName , Status ) ;
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
return Status ;
2009-09-09 13:49:04 +00:00
}
FileSize = FileStdInfo . EndOfFile . u . LowPart ;
2022-11-28 02:13:31 +00:00
/* Allocate memory for the file (add 1 byte for terminating NUL) */
FileBuffer = ExAllocatePool ( NonPagedPool , FileSize + 1 ) ;
2009-09-09 13:49:04 +00:00
if ( ! FileBuffer )
{
ZwClose ( hFile ) ;
2022-11-28 02:13:31 +00:00
DPRINT1 ( " Could not allocate %lu bytes for KDBinit file \n " , FileSize ) ;
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
return Status ;
2009-09-09 13:49:04 +00:00
}
/* Load file into memory */
2022-11-28 02:13:31 +00:00
Status = ZwReadFile ( hFile , NULL , NULL , NULL , & Iosb ,
FileBuffer , FileSize , NULL , NULL ) ;
2009-09-09 13:49:04 +00:00
ZwClose ( hFile ) ;
2005-03-12 09:40:07 +00:00
2023-01-09 11:11:19 +00:00
if ( ! NT_SUCCESS ( Status ) & & ( Status ! = STATUS_END_OF_FILE ) )
2009-09-09 13:49:04 +00:00
{
ExFreePool ( FileBuffer ) ;
2024-10-07 09:07:47 +00:00
DPRINT1 ( " Could not read KDBinit file into memory (Status 0x%lx) \n " , Status ) ;
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
return Status ;
2009-09-09 13:49:04 +00:00
}
2022-11-28 02:13:31 +00:00
FileSize = min ( FileSize , ( ULONG ) Iosb . Information ) ;
FileBuffer [ FileSize ] = ANSI_NULL ;
2009-09-09 13:49:04 +00:00
2022-11-28 02:13:31 +00:00
/* Interpret the KDBinit file by calling back into the debugger */
InterlockedExchangePointer ( ( PVOID * ) & KdbInitFileBuffer , FileBuffer ) ;
DbgBreakPointWithStatus ( DBG_STATUS_CONTROL_C ) ;
InterlockedExchangePointer ( ( PVOID * ) & KdbInitFileBuffer , NULL ) ;
2009-09-09 13:49:04 +00:00
ExFreePool ( FileBuffer ) ;
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
return STATUS_SUCCESS ;
2009-09-09 13:49:04 +00:00
}
2023-03-10 17:12:32 +00:00
2022-07-10 13:01:01 +00:00
/**
* @ brief Debug logger function .
*
* This function writes text strings into KdpDmesgBuffer , using it as
* a circular buffer . KdpDmesgBuffer contents can be later ( re ) viewed
* using the dmesg command . KdbDebugPrint ( ) protects KdpDmesgBuffer
* from simultaneous writes by use of KdpDmesgLogSpinLock .
* */
2023-03-10 17:12:32 +00:00
static VOID
NTAPI
KdbDebugPrint (
2023-03-27 23:33:55 +00:00
_In_ PCCH String ,
2022-07-10 13:01:01 +00:00
_In_ ULONG Length )
2023-03-10 17:12:32 +00:00
{
2022-07-10 13:01:01 +00:00
KIRQL OldIrql ;
ULONG beg , end , num ;
/* Avoid recursive calling if we already are in Dmesg mode */
if ( KdbpIsInDmesgMode )
return ;
if ( KdpDmesgBuffer = = NULL )
return ;
/* Acquire the printing spinlock without waiting at raised IRQL */
OldIrql = KdbpAcquireLock ( & KdpDmesgLogSpinLock ) ;
beg = KdpDmesgCurrentPosition ;
/* Invariant: always_true(KdpDmesgFreeBytes == KdpDmesgBufferSize); */
num = min ( Length , KdpDmesgFreeBytes ) ;
if ( num ! = 0 )
{
end = ( beg + num ) % KdpDmesgBufferSize ;
if ( end > beg )
{
RtlCopyMemory ( KdpDmesgBuffer + beg , String , Length ) ;
}
else
{
RtlCopyMemory ( KdpDmesgBuffer + beg , String , KdpDmesgBufferSize - beg ) ;
RtlCopyMemory ( KdpDmesgBuffer , String + ( KdpDmesgBufferSize - beg ) , end ) ;
}
KdpDmesgCurrentPosition = end ;
/* Counting the total bytes written */
KdbDmesgTotalWritten + = num ;
}
/* Release the spinlock */
KdbpReleaseLock ( & KdpDmesgLogSpinLock , OldIrql ) ;
/* Optional step(?): find out a way to notify about buffer exhaustion,
* and possibly fall into kbd to use dmesg command : user will read
* debug strings before they will be wiped over by next writes . */
2023-03-10 17:12:32 +00:00
}
/**
* @ brief Initializes the KDBG debugger .
*
* @ param [ in ] DispatchTable
* Pointer to the KD dispatch table .
*
* @ param [ in ] BootPhase
* Phase of initialization .
*
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
* @ return A status value .
2023-03-10 17:12:32 +00:00
* @ note Also known as " KdpKdbgInit " .
* */
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
NTSTATUS
2023-03-10 17:12:32 +00:00
NTAPI
KdbInitialize (
_In_ PKD_DISPATCH_TABLE DispatchTable ,
_In_ ULONG BootPhase )
{
2023-03-20 01:28:16 +00:00
/* Saves the different symbol-loading status across boot phases */
static ULONG LoadSymbols = 0 ;
2023-03-10 17:12:32 +00:00
if ( BootPhase = = 0 )
{
/* Write out the functions that we support for now */
DispatchTable - > KdpPrintRoutine = KdbDebugPrint ;
2023-03-29 00:06:35 +00:00
/* Check if we have a command line */
if ( KeLoaderBlock & & KeLoaderBlock - > LoadOptions )
{
/* Get the KDBG Settings */
KdbpGetCommandLineSettings ( KeLoaderBlock - > LoadOptions ) ;
}
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
/* Register for BootPhase 1 initialization and as a Provider */
DispatchTable - > KdpInitRoutine = KdbInitialize ;
2023-03-10 17:12:32 +00:00
InsertTailList ( & KdProviders , & DispatchTable - > KdProvidersList ) ;
}
2022-07-10 13:01:01 +00:00
else if ( BootPhase = = 1 )
{
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
/* Register for later BootPhase 2 reinitialization */
DispatchTable - > KdpInitRoutine = KdbInitialize ;
2022-07-10 13:01:01 +00:00
/* Initialize Dmesg support */
/* Allocate a buffer for Dmesg log buffer. +1 for terminating null,
* see kdbp_cli . c : KdbpCmdDmesg ( ) / 2 */
KdpDmesgBuffer = ExAllocatePoolZero ( NonPagedPool ,
KdpDmesgBufferSize + 1 ,
TAG_KDBG ) ;
/* Ignore failure if KdpDmesgBuffer is NULL */
KdpDmesgFreeBytes = KdpDmesgBufferSize ;
KdbDmesgTotalWritten = 0 ;
/* Initialize spinlock */
KeInitializeSpinLock ( & KdpDmesgLogSpinLock ) ;
}
2023-03-10 17:12:32 +00:00
2023-03-20 01:28:16 +00:00
/* Initialize symbols support in BootPhase 0 and 1 */
2023-03-10 17:12:32 +00:00
if ( BootPhase < = 1 )
{
2023-03-20 01:28:16 +00:00
LoadSymbols < < = 1 ;
LoadSymbols | = KdbSymInit ( BootPhase ) ;
2023-03-10 17:12:32 +00:00
}
2023-03-20 01:28:16 +00:00
if ( BootPhase = = 1 )
{
/* Announce ourselves */
CHAR buffer [ 60 ] ;
RtlStringCbPrintfA ( buffer , sizeof ( buffer ) ,
" KDBG debugger enabled - %s \r \n " ,
! ( LoadSymbols & 0x2 ) ? " No symbols loaded " :
! ( LoadSymbols & 0x1 ) ? " Kernel symbols loaded "
: " Loading symbols " ) ;
HalDisplayString ( buffer ) ;
}
if ( BootPhase > = 2 )
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
{
2022-11-28 02:13:31 +00:00
/* I/O is now set up for disk access: load the KDBinit file */
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470
+ KdpDebugLogInit: Add resources cleanup in failure code paths.
Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.
As a result, file debug logging is fixed.
The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.
The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261
Its rationale is as follows:
We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.
Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
KiSwitchToBootStack() -> KiSystemStartupBootStack()
-> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)
(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);
ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0;
HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
...
PsInitSystem(LoaderBlock)
PsCreateSystemThread(Phase1Initialization)
Phase1Initialization(Discard): ExpInitializationPhase = 1;
HalInitSystem(1, KeLoaderBlock);
...
Early initialization of Ob, Ex, Ke.
KdInitSystem(1, KeLoaderBlock);
...
KdDebuggerInitialize1(LoaderBlock);
...
IoInitSystem(LoaderBlock);
...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!
Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).
The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.
Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)
Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-01-09 18:35:18 +00:00
NTSTATUS Status = KdbpCliInit ( ) ;
/* Schedule an I/O reinitialization if needed */
if ( Status = = STATUS_OBJECT_NAME_NOT_FOUND | |
Status = = STATUS_OBJECT_PATH_NOT_FOUND )
{
DispatchTable - > KdpInitRoutine = KdbInitialize ;
}
}
return STATUS_SUCCESS ;
2023-03-10 17:12:32 +00:00
}
/* EOF */