* UPDATE HISTORY:
* Created 16/01/2005
*/
-
+
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
-#include <ctype.h>
-#include <internal/kdb.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
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 */
STATIC CHAR KdbCommandHistoryBuffer[2048]; /* Command history string ringbuffer */
STATIC PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL }; /* Command history ringbuffer */
ErrMsg += 2;
KdbpPrint("%*s%s\n", ExpressionErrOffset, "", ErrMsg);
}
-
+
return Ok;
}
STATIC BOOLEAN
KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[])
{
- INT i, len;
+ UINT i, len;
ULONGLONG Result = 0;
ULONG ul;
LONG l = 0;
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 */
Ok = KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result);
if (Ok)
KdbpPrint("0x%08lx %10lu\n", ul, ul);
}
}
-
+
return TRUE;
}
if (Argv[0][0] == 'r') /* regs */
{
- ULONG Esp;
- USHORT Ss;
-
- if (!(Tf->Cs & 1))
- {
- Esp = (ULONG)Tf->TempEsp;
- Ss = (USHORT)((ULONG)Tf->TempSegSs & 0xFFFF);
- }
- else
- {
- Esp = Tf->Esp;
- Ss = Tf->Ss;
- }
KdbpPrint("CS:EIP 0x%04x:0x%08x\n"
"SS:ESP 0x%04x:0x%08x\n"
" EAX 0x%08x EBX 0x%08x\n"
" ESI 0x%08x EDI 0x%08x\n"
" EBP 0x%08x\n",
Tf->Cs & 0xFFFF, Tf->Eip,
- Ss, Esp,
+ Tf->Ss, Tf->Esp,
Tf->Eax, Tf->Ebx,
Tf->Ecx, Tf->Edx,
Tf->Esi, Tf->Edi,
else if (Argv[0][0] == 'c') /* cregs */
{
ULONG Cr0, Cr2, Cr3, Cr4;
- struct __attribute__((packed)) {
- USHORT Limit;
- ULONG Base;
- } Gdtr, Ldtr, Idtr;
+ KDESCRIPTOR Gdtr, Ldtr, Idtr;
ULONG Tr;
STATIC CONST PCHAR Cr0Bits[32] = { " PE", " MP", " EM", " TS", " ET", " NE", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
" PCE", " OSFXSR", " OSXMMEXCPT", NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
+
Cr0 = KdbCurrentTrapFrame->Cr0;
Cr2 = KdbCurrentTrapFrame->Cr2;
Cr3 = KdbCurrentTrapFrame->Cr3;
Cr4 = KdbCurrentTrapFrame->Cr4;
/* Get descriptor table regs */
- asm volatile("sgdt %0" : : "m"(Gdtr));
- asm volatile("sldt %0" : : "m"(Ldtr));
- asm volatile("sidt %0" : : "m"(Idtr));
+ asm volatile("sgdt %0" : : "m"(Gdtr.Limit));
+ asm volatile("sldt %0" : : "m"(Ldtr.Limit));
+ asm volatile("sidt %0" : : "m"(Idtr.Limit));
/* Get the task register */
asm volatile("str %0" : "=g"(Tr));
-
+
/* Display the control registers */
KdbpPrint("CR0 0x%08x ", Cr0);
for (i = 0; i < 32; i++)
if ((Cr4 & (1 << i)) != 0)
KdbpPrint(Cr4Bits[i]);
}
-
+
/* Display the descriptor table regs */
KdbpPrint("\nGDTR Base 0x%08x Size 0x%04x\n", Gdtr.Base, Gdtr.Limit);
KdbpPrint("LDTR Base 0x%08x Size 0x%04x\n", Ldtr.Base, Ldtr.Limit);
}
KdbpPrint("Frames:\n");
- while (Frame != 0)
+ for (;;)
{
+ if (Frame == 0)
+ break;
if (!NT_SUCCESS(KdbpSafeReadMemory(&Address, (PVOID)(Frame + sizeof(ULONG_PTR)), sizeof (ULONG_PTR))))
{
- KdbpPrint("Couldn't access memory at 0x%x!\n", Frame + sizeof(ULONG_PTR));
+ KdbpPrint("Couldn't access memory at 0x%p!\n", Frame + sizeof(ULONG_PTR));
break;
}
if (!KdbSymPrintAddress((PVOID)Address))
KdbpPrint("<%08x>\n", Address);
else
KdbpPrint("\n");
+ if (Address == 0)
+ break;
if (!NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof (ULONG_PTR))))
{
- KdbpPrint("Couldn't access memory at 0x%x!\n", Frame);
+ KdbpPrint("Couldn't access memory at 0x%p!\n", Frame);
break;
}
}
-
+
return TRUE;
}
KdbpCmdStep(ULONG Argc, PCHAR Argv[])
{
ULONG Count = 1;
-
+
if (Argc > 1)
{
Count = strtoul(Argv[1], NULL, 0);
return TRUE;
}
}
-
+
if (Argv[0][0] == 'n')
KdbSingleStepOver = TRUE;
else
KdbpPrint("No breakpoints.\n");
return TRUE;
}
-
+
KdbpPrint("Breakpoints:\n");
do
{
KDB_BREAKPOINT_TYPE Type;
UCHAR Size = 0;
KDB_ACCESS_TYPE AccessType = 0;
- INT AddressArgIndex, ConditionArgIndex, i;
+ UINT AddressArgIndex, ConditionArgIndex, i;
BOOLEAN Global = TRUE;
-
+
if (Argv[0][2] == 'x') /* software breakpoint */
{
if (Argc < 2)
else /* memory breakpoint */
{
ASSERT(Argv[0][2] == 'm');
-
+
if (Argc < 2)
{
KdbpPrint("bpm: Access type argument required (one of r, w, rw, x)\n");
KdbpPrint("bpm: Unknown access type '%s'\n", Argv[1]);
return TRUE;
}
-
+
if (Argc < 3)
{
KdbpPrint("bpm: %s argument required.\n", AccessType == KdbAccessExec ? "Address" : "Memory size");
KdbpPrint("bpm: Unknown memory size '%s'\n", Argv[2]);
return TRUE;
}
-
+
if (Argc <= AddressArgIndex)
{
KdbpPrint("bpm: Address argument required.\n");
Type = KdbBreakPointHardware;
}
-
+
/* Put the arguments back together */
ConditionArgIndex = -1;
for (i = AddressArgIndex; i < (Argc-1); i++)
KdbpInsertBreakPoint(Address, Type, Size, AccessType,
(ConditionArgIndex < 0) ? NULL : Argv[ConditionArgIndex],
Global, NULL);
-
+
return TRUE;
}
if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
{
Process = KdbCurrentProcess;
-
+
if (Argc >= 3)
{
ul = strtoul(Argv[2], &pend, 0);
return TRUE;
}
}
-
+
Entry = Process->ThreadListHead.Flink;
if (Entry == &Process->ThreadListHead)
{
if (Thread->Tcb.TrapFrame != NULL)
{
- Esp = (PULONG)Thread->Tcb.TrapFrame->Esp;
+ if (Thread->Tcb.TrapFrame->PreviousMode == KernelMode)
+ Esp = (PULONG)Thread->Tcb.TrapFrame->TempEsp;
+ else
+ Esp = (PULONG)Thread->Tcb.TrapFrame->Esp;
Ebp = (PULONG)Thread->Tcb.TrapFrame->Ebp;
Eip = Thread->Tcb.TrapFrame->Eip;
}
Ebp = (PULONG)Esp[4];
Eip = 0;
if (Ebp != NULL) /* FIXME: Should we attach to the process to read Ebp[1]? */
- KdbpSafeReadMemory(&Eip, Ebp + 1, sizeof (Eip));;
+ KdbpSafeReadMemory(&Eip, Ebp + 1, sizeof (Eip));
}
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,
Ebp,
Eip,
str2);
-
+
Entry = Entry->Flink;
}
while (Entry != &Process->ThreadListHead);
return TRUE;
}
}
-
+
if (Thread->Tcb.State < (DeferredReady + 1))
State = ThreadStateToString[Thread->Tcb.State];
else
KdbpPrint("No processes in the system!\n");
return TRUE;
}
-
+
KdbpPrint(" PID State Filename\n");
do
{
- Process = CONTAINING_RECORD(Entry, EPROCESS, ProcessListEntry);
+ Process = CONTAINING_RECORD(Entry, EPROCESS, ActiveProcessLinks);
if (Process == KdbCurrentProcess)
{
str2 = "";
}
- State = ((Process->Pcb.State == PROCESS_STATE_TERMINATED) ? "Terminated" :
- ((Process->Pcb.State == PROCESS_STATE_ACTIVE) ? "Active" : "Unknown"));
-
+ 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);
}
}
- State = ((Process->Pcb.State == PROCESS_STATE_TERMINATED) ? "Terminated" :
- ((Process->Pcb.State == PROCESS_STATE_ACTIVE) ? "Active" : "Unknown"));
+ 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"
if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0]);
Address = (ULONG_PTR)Result;
-
+
if (!KdbpSymFindModuleByAddress((PVOID)Address, &Info))
{
- KdbpPrint("No module containing address 0x%x found!\n", Address);
+ KdbpPrint("No module containing address 0x%p found!\n", Address);
return TRUE;
}
DisplayOnlyOneModule = TRUE;
i = 0;
ul = 1 << 2;
}
-
+
if (Reg.Limit < 7)
{
KdbpPrint("%s descriptor table is empty.\n",
}
}
}
-
+
return TRUE;
}
STATIC BOOLEAN
KdbpCmdPcr(ULONG Argc, PCHAR Argv[])
{
- PKPCR Pcr = KeGetCurrentKPCR();
+ PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR();
KdbpPrint("Current PCR is at 0x%08x.\n", (INT)Pcr);
KdbpPrint(" Tib.ExceptionList: 0x%08x\n"
" MinorVersion: 0x%04x\n"
" SetMember: 0x%08x\n"
" StallScaleFactor: 0x%08x\n"
- " DebugActive: 0x%02x\n"
- " ProcessorNumber: 0x%02x\n"
+ " Number: 0x%02x\n"
" L2CacheAssociativity: 0x%02x\n"
" VdmAlert: 0x%08x\n"
" L2CacheSize: 0x%08x\n"
" InterruptMode: 0x%08x\n",
- Pcr->Tib.ExceptionList, Pcr->Tib.StackBase, Pcr->Tib.StackLimit,
- Pcr->Tib.SubSystemTib, Pcr->Tib.FiberData, Pcr->Tib.ArbitraryUserPointer,
- Pcr->Tib.Self, Pcr->Self, Pcr->Prcb, Pcr->Irql, Pcr->IRR, Pcr->IrrActive,
+ Pcr->NtTib.ExceptionList, Pcr->NtTib.StackBase, Pcr->NtTib.StackLimit,
+ Pcr->NtTib.SubSystemTib, Pcr->NtTib.FiberData, Pcr->NtTib.ArbitraryUserPointer,
+ Pcr->NtTib.Self, Pcr->Self, 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->DebugActive, Pcr->ProcessorNumber, Pcr->L2CacheAssociativity,
+ Pcr->Number, Pcr->L2CacheAssociativity,
Pcr->VdmAlert, Pcr->L2CacheSize, Pcr->InterruptMode);
-
+
return TRUE;
}
STATIC BOOLEAN
KdbpCmdSet(ULONG Argc, PCHAR Argv[])
{
- LONG l;
+ ULONG l;
BOOLEAN First;
PCHAR pend = 0;
KDB_ENTER_CONDITION ConditionFirst = KdbDoNotEnter;
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)
{
l = -1;
else
{
- l = (LONG)strtoul(Argv[2], &pend, 0);
+ l = strtoul(Argv[2], &pend, 0);
if (Argv[2] == pend)
{
for (l = 0; l < RTL_NUMBER_OF(ExceptionNames); l++)
}
}
}
+ 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;
+ else
+ KdbpPrint("Unknown setting '%s'.\n", Argv[2]);
+ }
+ }
else
KdbpPrint("Unknown setting '%s'.\n", Argv[1]);
STATIC BOOLEAN TerminalReportsSize = TRUE;
CHAR c = '\0';
PCHAR p, p2;
- INT Length;
- INT i, j;
+ UINT Length;
+ UINT i, j;
INT RowsPrintedByTerminal;
ULONG ScanCode;
va_list ap;
if (!TerminalInitialized)
{
DbgPrint("\x1b[7h"); /* Enable linewrap */
-
+
/* Query terminal type */
/*DbgPrint("\x1b[Z");*/
DbgPrint("\x05");
-
+
TerminalInitialized = TRUE;
Length = 0;
for (;;)
if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
(KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */
{
- if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalReportsSize)
+ if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize)
{
/* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */
TerminalReportsSize = FALSE;
while (p[0] != '\0')
{
i = strcspn(p, "\n");
-
+
/* Calculate the number of lines which will be printed in the terminal
* when outputting the current line
*/
RowsPrintedByTerminal = 0;
if (p[i] == '\n')
RowsPrintedByTerminal++;
-
+
/*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
/* Display a prompt if we printed one screen full of text */
- if ((KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
+ if (KdbNumberOfRowsTerminal > 0 &&
+ (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal)
{
if (KdbNumberOfColsPrinted > 0)
DbgPrint("\n");
{
c = '\0';
}
-
+
/* Remove escape sequences from the line if there's no terminal connected */
if (!TerminalConnected)
{
KdbpCommandHistoryAppend(
IN PCHAR Command)
{
- LONG Length1 = strlen(Command) + 1;
- LONG Length2 = 0;
+ ULONG Length1 = strlen(Command) + 1;
+ ULONG Length2 = 0;
INT i;
PCHAR Buffer;
-
+
ASSERT(Length1 <= RTL_NUMBER_OF(KdbCommandHistoryBuffer));
if (Length1 <= 1 ||
/* Calculate Length1 and Length2 */
Buffer = KdbCommandHistoryBuffer + KdbCommandHistoryBufferIndex;
KdbCommandHistoryBufferIndex += Length1;
- if (KdbCommandHistoryBufferIndex >= RTL_NUMBER_OF(KdbCommandHistoryBuffer))
+ if (KdbCommandHistoryBufferIndex >= (LONG)RTL_NUMBER_OF(KdbCommandHistoryBuffer))
{
KdbCommandHistoryBufferIndex -= RTL_NUMBER_OF(KdbCommandHistoryBuffer);
Length2 = KdbCommandHistoryBufferIndex;
NextKey = '\0';
}
- if ((Buffer - Orig) >= (Size - 1))
+ if ((ULONG)(Buffer - Orig) >= (Size - 1))
{
/* Buffer is full, accept only newlines */
if (Key != '\n')
if (CmdHistIndex > 0 && CmdHistIndex != KdbCommandHistoryIndex)
{
i = CmdHistIndex + 1;
- if (i >= RTL_NUMBER_OF(KdbCommandHistory))
+ if (i >= (INT)RTL_NUMBER_OF(KdbCommandHistory))
i = 0;
if (KdbCommandHistory[i] != NULL)
{
p++;
if (*p == '\0')
break;
-
+
i = strcspn(p, "\t ");
Argv[Argc++] = p;
p += i;
/* Read a command and remember it */
KdbpReadCommand(Command, sizeof (Command));
KdbpCommandHistoryAppend(Command);
-
+
/* Reset the number of rows/cols printed and output aborted state */
KdbNumberOfRowsPrinted = KdbNumberOfColsPrinted = 0;
KdbOutputAborted = FALSE;
-
+
/* Call the command */
Continue = KdbpDoCommand(Command);
} while (Continue);
VOID
KdbpCliModuleLoaded(IN PUNICODE_STRING Name)
{
- return;
+ if (!KdbBreakOnModuleLoad)
+ return;
DbgPrint("Module %wZ loaded.\n", Name);
DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
CHAR c;
/* Execute the commands in the init file */
- DbgPrint("KDB: Executing KDBinit file...\n");
+ DPRINT("KDB: Executing KDBinit file...\n");
p1 = KdbInitFileBuffer;
while (p1[0] != '\0')
{
{
KdbpDoCommand(p1);
}
-
+
p1[i] = c;
}
p1 += i;
while (p1[0] == '\r' || p1[0] == '\n')
p1++;
}
- DbgPrint("KDB: KDBinit executed\n");
+ DPRINT("KDB: KDBinit executed\n");
}
/*!\brief Called when KDB is initialized
/* Initialize the object attributes */
RtlInitUnicodeString(&FileName, L"\\SystemRoot\\system32\\drivers\\etc\\KDBinit");
InitializeObjectAttributes(&ObjectAttributes, &FileName, 0, NULL, NULL);
-
+
/* Open the file */
Status = ZwOpenFile(&hFile, FILE_READ_DATA, &ObjectAttributes, &Iosb, 0,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
DPRINT("Could not read KDBinit file into memory (Status 0x%lx)\n", Status);
return;
}
- FileSize = min(FileSize, Iosb.Information);
+ FileSize = min(FileSize, (INT)Iosb.Information);
FileBuffer[FileSize] = '\0';
/* Enter critical section */