--- trunk/reactos/ntoskrnl/dbg/kdb_cli.c 2005-03-12 09:21:59 UTC (rev 13964)
+++ trunk/reactos/ntoskrnl/dbg/kdb_cli.c 2005-03-12 09:40:07 UTC (rev 13965)
@@ -1,2320 +1,2320 @@
-/*
- * 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.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
- *
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/dbg/kdb_cli.c
- * PURPOSE: Kernel debugger command line interface
- * PROGRAMMER: Gregor Anich (blight@blight.eu.org)
- * UPDATE HISTORY:
- * Created 16/01/2005
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "kdb.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* DEFINES *******************************************************************/
-
-#define KEY_BS 8
-#define KEY_ESC 27
-#define KEY_DEL 127
-
-#define KEY_SCAN_UP 72
-#define KEY_SCAN_DOWN 80
-
-#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) \
- ((state) == NPX_STATE_INVALID ? "Invalid" : \
- ((state) == NPX_STATE_VALID ? "Valid" : \
- ((state) == NPX_STATE_DIRTY ? "Dirty" : "Unknown")))
-
-/* PROTOTYPES ****************************************************************/
-
-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[]);
-STATIC BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]);
-
-STATIC BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]);
-STATIC BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
-STATIC BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
-
-/* GLOBALS *******************************************************************/
-
-STATIC BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
-
-STATIC CHAR KdbCommandHistoryBuffer[2048]; /* Command history string ringbuffer */
-STATIC PCHAR KdbCommandHistory[sizeof(KdbCommandHistoryBuffer) / 8] = { NULL }; /* Command history ringbuffer */
-STATIC LONG KdbCommandHistoryBufferIndex = 0;
-STATIC LONG KdbCommandHistoryIndex = 0;
-
-STATIC ULONG KdbNumberOfRowsPrinted = 0;
-STATIC ULONG KdbNumberOfColsPrinted = 0;
-STATIC BOOLEAN KdbOutputAborted = FALSE;
-STATIC LONG KdbNumberOfRowsTerminal = -1;
-STATIC LONG KdbNumberOfColsTerminal = -1;
-
-PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */
-
-STATIC CONST struct
-{
- PCHAR Name;
- PCHAR Syntax;
- PCHAR Help;
- BOOLEAN (*Fn)(ULONG Argc, PCHAR Argv[]);
-} KdbDebuggerCommands[] = {
- /* Data */
- { NULL, NULL, "Data", NULL },
- { "?", "? expression", "Evaluate expression.", KdbpCmdEvalExpression },
- { "disasm", "disasm [address] [L count]", "Disassemble count instructions at address.", KdbpCmdDisassembleX },
- { "x", "x [address] [L count]", "Display count dwords, starting at addr.", KdbpCmdDisassembleX },
- { "regs", "regs", "Display general purpose registers.", KdbpCmdRegs },
- { "cregs", "cregs", "Display control registers.", KdbpCmdRegs },
- { "sregs", "sregs", "Display status registers.", KdbpCmdRegs },
- { "dregs", "dregs", "Display debug registers.", KdbpCmdRegs },
- { "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame addr", KdbpCmdBackTrace },
-
- /* Flow control */
- { NULL, NULL, "Flow control", NULL },
- { "cont", "cont", "Continue execution (leave debugger)", KdbpCmdContinue },
- { "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 },
- { "gdt", "gdt", "Display global descriptor table.", KdbpCmdGdtLdtIdt },
- { "ldt", "ldt", "Display local descriptor table.", KdbpCmdGdtLdtIdt },
- { "idt", "idt", "Display interrupt descriptor table.", KdbpCmdGdtLdtIdt },
- { "pcr", "pcr", "Display processor control region.", KdbpCmdPcr },
- { "tss", "tss", "Display task state segment.", KdbpCmdTss },
-
- /* Others */
- { NULL, NULL, "Others", NULL },
- { "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck },
- { "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet },
- { "help", "help", "Display help screen.", KdbpCmdHelp }
-};
-
-/* 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.
- */
-STATIC BOOLEAN
-KdbpEvaluateExpression(
- IN PCHAR Expression,
- IN LONG ErrOffset,
- OUT PULONGLONG Result)
-{
- 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;
-}
-
-/*!\brief Evaluates an expression and displays the result.
- */
-STATIC BOOLEAN
-KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[])
-{
- INT i, len;
- 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 */
- Ok = KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result);
- 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;
-}
-
-/*!\brief Disassembles 10 instructions at eip or given address or
- * displays 16 dwords from memory at given address.
- */
-STATIC BOOLEAN
-KdbpCmdDisassembleX(ULONG Argc, PCHAR Argv[])
-{
- ULONG Count;
- ULONG ul;
- INT i;
- ULONGLONG Result = 0;
- ULONG_PTR Address = KdbCurrentTrapFrame->Tf.Eip;
- 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)
- {
- if (!KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result))
- return TRUE;
- if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
- KdbpPrint("Warning: Address %I64x is beeing truncated\n");
- 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)
- {
- if (!KdbSymPrintAddress((PVOID)Address))
- KdbpPrint("<%x>:", Address);
- 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)
- {
- if (!KdbSymPrintAddress((PVOID)Address))
- KdbpPrint("<%08x>: ", Address);
- else
- KdbpPrint(": ");
- InstLen = KdbpDisassemble(Address, KdbUseIntelSyntax);
- if (InstLen < 0)
- {
- KdbpPrint("<INVALID>\n");
- return TRUE;
- }
- KdbpPrint("\n");
- Address += InstLen;
- }
- }
-
- return TRUE;
-}
-
-/*!\brief Displays CPU registers.
- */
-STATIC BOOLEAN
-KdbpCmdRegs(ULONG Argc, PCHAR Argv[])
-{
- PKTRAP_FRAME Tf = &KdbCurrentTrapFrame->Tf;
- 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 */
- {
- 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",
- Tf->Cs & 0xFFFF, Tf->Eip,
- Tf->Ss, Tf->Esp,
- Tf->Eax, Tf->Ebx,
- Tf->Ecx, Tf->Edx,
- Tf->Esi, Tf->Edi,
- Tf->Ebp);
- KdbpPrint("EFLAGS 0x%08x ", Tf->Eflags);
- for (i = 0; i < 32; i++)
- {
- if (i == 1)
- {
- if ((Tf->Eflags & (1 << 1)) == 0)
- KdbpPrint(" !BIT1");
- }
- else if (i == 12)
- {
- KdbpPrint(" IOPL%d", (Tf->Eflags >> 12) & 3);
- }
- else if (i == 13)
- {
- }
- else if ((Tf->Eflags & (1 << i)) != 0)
- KdbpPrint(EflagsBits[i]);
- }
- KdbpPrint("\n");
- }
- else if (Argv[0][0] == 'c') /* cregs */
- {
- ULONG Cr0, Cr2, Cr3, Cr4;
- struct __attribute__((packed)) {
- USHORT Limit;
- ULONG Base;
- } 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,
- " WP", NULL, " AM", NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, " NW", " CD", " PG" };
- STATIC CONST PCHAR Cr4Bits[32] = { " VME", " PVI", " TSD", " DE", " PSE", " PAE", " MCE", " PGE",
- " 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));
-
- /* 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 (Cr0Bits[i] == NULL)
- continue;
- if ((Cr0 & (1 << i)) != 0)
- KdbpPrint(Cr0Bits[i]);
- }
- KdbpPrint("\nCR2 0x%08x\n", Cr2);
- KdbpPrint("CR3 0x%08x Pagedir-Base 0x%08x %s%s\n", Cr3, (Cr3 & 0xfffff000),
- (Cr3 & (1 << 3)) ? " PWT" : "", (Cr3 & (1 << 4)) ? " PCD" : "" );
- KdbpPrint("CR4 0x%08x ", Cr4);
- for (i = 0; i < 32; i++)
- {
- if (Cr4Bits[i] == NULL)
- continue;
- 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("IDTR Base 0x%08x Size 0x%04x\n", Idtr.Base, Idtr.Limit);
- }
- else if (Argv[0][0] == 's') /* sregs */
- {
- KdbpPrint("CS 0x%04x Index 0x%04x %cDT RPL%d\n",
- Tf->Cs & 0xffff, (Tf->Cs & 0xffff) >> 3,
- (Tf->Cs & (1 << 2)) ? 'L' : 'G', Tf->Cs & 3);
- KdbpPrint("DS 0x%04x Index 0x%04x %cDT RPL%d\n",
- Tf->Ds, Tf->Ds >> 3, (Tf->Ds & (1 << 2)) ? 'L' : 'G', Tf->Ds & 3);
- KdbpPrint("ES 0x%04x Index 0x%04x %cDT RPL%d\n",
- Tf->Es, Tf->Es >> 3, (Tf->Es & (1 << 2)) ? 'L' : 'G', Tf->Es & 3);
- KdbpPrint("FS 0x%04x Index 0x%04x %cDT RPL%d\n",
- Tf->Fs, Tf->Fs >> 3, (Tf->Fs & (1 << 2)) ? 'L' : 'G', Tf->Fs & 3);
- KdbpPrint("GS 0x%04x Index 0x%04x %cDT RPL%d\n",
- Tf->Gs, Tf->Gs >> 3, (Tf->Gs & (1 << 2)) ? 'L' : 'G', Tf->Gs & 3);
- KdbpPrint("SS 0x%04x Index 0x%04x %cDT RPL%d\n",
- Tf->Ss, Tf->Ss >> 3, (Tf->Ss & (1 << 2)) ? 'L' : 'G', Tf->Ss & 3);
- }
- 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",
- Tf->Dr0, Tf->Dr1, Tf->Dr2, Tf->Dr3,
- Tf->Dr6, Tf->Dr7);
- }
- return TRUE;
-}
-
-/*!\brief Displays a backtrace.
- */
-STATIC BOOLEAN
-KdbpCmdBackTrace(ULONG Argc, PCHAR Argv[])
-{
- ULONG Count;
- ULONG ul;
- ULONGLONG Result = 0;
- ULONG_PTR Frame = KdbCurrentTrapFrame->Tf.Ebp;
- 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)
- {
- 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++;
- }
-
- /* Check if frame addr or thread id is given. */
- if (Argc > 1)
- {
- if (Argv[1][0] == '*')
- {
- Argv[1]++;
- /* Evaluate the expression */
- if (!KdbpEvaluateExpression(Argv[1], sizeof("kdb:> ")-1 + (Argv[1]-Argv[0]), &Result))
- return TRUE;
- if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
- KdbpPrint("Warning: Address %I64x is beeing truncated\n");
- Frame = (ULONG_PTR)Result;
- }
- else
- {
-
- KdbpPrint("Thread backtrace not supported yet!\n");
- return TRUE;
- }
- }
-
- KdbpPrint("Frames:\n");
- while (Frame != 0)
- {
- 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));
- break;
- }
- if (!KdbSymPrintAddress((PVOID)Address))
- KdbpPrint("<%08x>\n", Address);
- else
- KdbpPrint("\n");
- if (!NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof (ULONG_PTR))))
- {
- KdbpPrint("Couldn't access memory at 0x%x!\n", Frame);
- break;
- }
- }
-
- return TRUE;
-}
-
-/*!\brief Continues execution of the system/leaves KDB.
- */
-STATIC BOOLEAN
-KdbpCmdContinue(ULONG Argc, PCHAR Argv[])
-{
- /* Exit the main loop */
- return FALSE;
-}
-
-/*!\brief Continues execution of the system/leaves KDB.
- */
-STATIC BOOLEAN
-KdbpCmdStep(ULONG Argc, PCHAR Argv[])
-{
- 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;
-}
-
-/*!\brief Lists breakpoints.
- */
-STATIC BOOLEAN
-KdbpCmdBreakPointList(ULONG Argc, PCHAR Argv[])
-{
- 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;
- sprintf(Buffer, " PID 0x%08lx",
- (ULONG)(Process ? Process->UniqueProcessId : INVALID_HANDLE_VALUE));
- }
-
- if (Type == KdbBreakPointSoftware || Type == KdbBreakPointTemporary)
- {
- KdbpPrint(" %s%03d BPX 0x%08x%s%s%s%s%s\n",
- str1, l, Address,
- Enabled ? "" : " disabled",
- GlobalOrLocal,
- ConditionExpr ? " IF " : "",
- ConditionExpr ? ConditionExpr : "",
- str2);
- }
- 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);
-
- return TRUE;
-}
-
-/*!\brief Enables, disables or clears a breakpoint.
- */
-STATIC BOOLEAN
-KdbpCmdEnableDisableClearBreakPoint(ULONG Argc, PCHAR Argv[])
-{
- 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;
-}
-
-/*!\brief Sets a software or hardware (memory) breakpoint at the given address.
- */
-STATIC BOOLEAN
-KdbpCmdBreakPoint(ULONG Argc, PCHAR Argv[])
-{
- ULONGLONG Result = 0;
- ULONG_PTR Address;
- KDB_BREAKPOINT_TYPE Type;
- UCHAR Size = 0;
- KDB_ACCESS_TYPE AccessType = 0;
- INT AddressArgIndex, ConditionArgIndex, i;
- BOOLEAN Global = TRUE;
-
- if (Argv[0][2] == 'x') /* software breakpoint */
- {
- if (Argc < 2)
- {
- KdbpPrint("bpx: Address argument required.\n");
- return TRUE;
- }
-
- 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");
- return TRUE;
- }
-
- 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]);
- return TRUE;
- }
-
- 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;
- if (ConditionArgIndex >= Argc)
- {
- 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],
- sizeof("kdb:> ")-1 + (Argv[AddressArgIndex]-Argv[0]),
- &Result))
- {
- return TRUE;
- }
- if (Result > (ULONGLONG)(~((ULONG_PTR)0)))
- KdbpPrint("%s: Warning: Address %I64x is beeing truncated\n", Argv[0]);
- 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;
- PULONG Esp;
- PULONG Ebp;
- ULONG Eip;
- ULONG ul = 0;
- PCHAR State, pend, str1, str2;
- STATIC CONST PCHAR ThreadStateToString[THREAD_STATE_MAX] =
- { "Initialized", "Ready", "Running",
- "Suspended", "Frozen", "Terminated1",
- "Terminated2", "Blocked" };
- ASSERT(KdbCurrentProcess != NULL);
-
- if (Argc >= 2 && _stricmp(Argv[1], "list") == 0)
- {
- Process = KdbCurrentProcess;
-
- if (Argc >= 3)
- {
- ul = strtoul(Argv[2], &pend, 0);
- 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;
- }
- }
-
- Entry = Process->ThreadListHead.Flink;
- if (Entry == &Process->ThreadListHead)
- {
- if (Argc >= 3)
- KdbpPrint("No threads in process 0x%08x!\n", ul);
- else
- KdbpPrint("No threads in current process!\n");
- return TRUE;
- }
-
- 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 = "";
- }
-
- if (Thread->Tcb.TrapFrame != NULL)
- {
- Esp = (PULONG)Thread->Tcb.TrapFrame->Esp;
- Ebp = (PULONG)Thread->Tcb.TrapFrame->Ebp;
- Eip = Thread->Tcb.TrapFrame->Eip;
- }
- else
- {
- Esp = (PULONG)Thread->Tcb.KernelStack;
- 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));;
- }
- if (Thread->Tcb.State < THREAD_STATE_MAX)
- 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,
- Ebp,
- Eip,
- str2);
-
- Entry = Entry->Flink;
- }
- while (Entry != &Process->ThreadListHead);
- }
- else if (Argc >= 2 && _stricmp(Argv[1], "attach") == 0)
- {
- if (Argc < 3)
- {
- KdbpPrint("thread attach: thread id argument required!\n");
- return TRUE;
- }
-
- ul = strtoul(Argv[2], &pend, 0);
- if (Argv[2] == pend)
- {
- KdbpPrint("thread attach: '%s' is not a valid thread id!\n", Argv[2]);
- return TRUE;
- }
- if (!KdbpAttachToThread((PVOID)ul))
- {
- return TRUE;
- }
- KdbpPrint("Attached to thread 0x%08x.\n", ul);
- }
- else
- {
- Thread = KdbCurrentThread;
-
- if (Argc >= 2)
- {
- ul = strtoul(Argv[1], &pend, 0);
- 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)))
[truncated at 1000 lines; 4259 more skipped]